【編者的話】RPM(Red Hat Package Manager)是用於 Linux 分發版的最常見的軟件包管理器。因為它允許分發已編譯的軟件,所以用戶只用一個命令就可以安裝軟件。而RPM包的構建相當繁瑣,並且對環境的要求比較高, 本文作者介紹了如何借助Docker來構建可以適用多個平台的RPM包。
在一個內部項目中,我一直在思考如何通過非CI工具/流程生成RPM包,我想手動生成RPM包,這樣我可以測試它們是否能正常安裝,並用於正常的冒煙測試(譯者注:冒煙測試就是在每日構建完成後,對系統的基本功能進行簡單的測試。這種測試強調功能的覆蓋率,而不對功能的正確性進行驗證)。
在我們的CI流程中,Docker算是個全能手,所以我也在想能否將Docker鏡像和RPM結合起來。理想的情況下,讓RPM與Docker集成, 這樣,創建RPM包的過程其實就是在構建一個Docker鏡像。基本上,RPM包的%prep部分的構建可以在一個特殊的Docker鏡像中快速完成,然 後將生成的RPM包返回給主機。
這種方式的的優點在於,你的RPM包是在一個相對封閉且可再生的環境中構建的,所以你可以快速的為CentOS、Fedora、RHEL等其它系統構建RPM包。
我相信還有其它的一些變通方法也可以完成這樣的工作,比如chroot之類的。但如果在RPM中內建這種打包機制(通過chroot/Docker或者別的容器技術抽象而來的系統來完成打包工作)的話,我想會更好。
由於我的項目還沒有完成,所以我只是對我的想法進行了驗證:簡單構建一個包含依賴的鏡像。
這是一個使用PBR生成版本 的Python項目。 首先我在build目錄中生成一個tarball,然後得到生成的版本號,緊接著修改spec文件中的版本號,然後開始用新的tar包和spec文件構建 鏡像。最後運行鏡像,並掛載卷(Volume)到本地目錄。當運行容器中的start.sh腳本之後,鏡像就運行起來了。
start.sh相當簡單。 它構建好RPM包後,以root身份把它拷貝到卷目錄下, 還可以從主機上將它拷貝到output目錄。我沒有將它拷貝或者說更新到類似swift之類的對象存儲系統,因為我還要在CI中使用它,所以就使用本地文件拷貝了。
在SPECS/project.spec以及 SOURCES/* 是標准RPM包需要的spec文件,源文件和patch文件。需要做的唯一一件事是定義%define_version宏,並在spec文件中使用它。下面是我的一些腳本。
主腳本build.sh。 可以從CI中運行。
#!/bin/bashset -exf PROJECT=myproject CURDIR=$(dirname $(readlink -f $0)) TOPDIR=$(git rev-parse --show-topklevel 2>/dev/null) rm -rf ${CURDIR}/.build/rpm mkdir -p ${CURDIR}/.build/rpm/{BUILD,SRPMS,SPECS,RPMS/noarch} cp -r ${CURDIR}/SOURCES ${CURDIR}/.build/rpm pushd ${TOPDIR} >/dev/null python setup.py sdist --dist-dir ${CURDIR}/.build/rpm/SOURCES/ SALADIER_VERSION=$(sed -n '/^Version/ { s/.* //; p}' ${PROJECT}.egg-info/PKG-INFO) popd >/dev/null sed -e "s/%define _version.*/%define _version ${SALADIER_VERSION}/" ${CURDIR}/SPECS/${MYROJECT}.spec > \ ${CURDIR}/.build/rpm/SPECS/${MYPROJECT}.spec docker build -t chmouel/buildrpm ${CURDIR} docker run -v $CURDIR/.build:/data -it chmouel/buildrpm if [[ -n ${ARTIFACT_DIR} ]];then rm -rf ${ARTIFACT_DIR}/rpm cp -a ${CURDIR}/.build/output ${ARTIFACT_DIR}/rpm fi
DockerFile,為Docker 緩存做了一些優化:
FROM fedora:21 MAINTAINER Chmouel Boudjnah <[email protected]> RUN yum -y groupinstall 'Development Tools' RUN yum -y install fedora-packager RUN yum -y install yum-utils RUN yum -y install sudo RUN sed -i.bak -n -e '/^Defaults.*requiretty/ { s/^/# /;};/^%wheel.*ALL$/ { s/^/# / ;} ;/^#.*wheel.*NOPASSWD/ { s/^#[ ]*//;};p' /etc/sudoers RUN yum install -y https://rdo.fedorapeople.org/rdo-release.rpm# This is an optimisation for caching, since using the auto generated one will# make docker always run the builddep steps since new file ADD SPECS/project.spec /tmp/ RUN yum-builddep -y /tmp/project.spec ADD bin/start.sh /start.sh RUN useradd -s /bin/bash -G adm,wheel,systemd-journal -m rpm WORKDIR /home/rpm CMD /start.sh ADD .build/rpm/ /home/rpm/rpmbuild/ RUN chown -R rpm: /home/rpm USER rpm
以及從容器中運行的start.sh腳本:
#!/bin/bash# script run inside the container rpmbuild -ba rpmbuild/SPECS/project.spec || exit 1[[ -d /data ]] || exit 0 sudo rm -rf /data/output sudo cp -a rpmbuild/RPMS/noarch /data/output
腳本可能無法直接在你的環境中使用,但至少能讓你了解這個idea。
制作自己的rpm包 http://www.linuxidc.com/Linux/2013-06/86435.htm
Linux 下rpm安裝後的目錄結構和一些配置 http://www.linuxidc.com/Linux/2013-06/85761.htm
rpm與yum的綜合性介紹與示例演示 http://www.linuxidc.com/Linux/2013-05/84480.htm
RedHat Linux---rpm 命令詳解 http://www.linuxidc.com/Linux/2013-03/81971.htm
使用FPM輕松制作RPM包 http://www.linuxidc.com/linux/2014-06/103019.htm
Docker 的詳細介紹:請點這裡
Docker 的下載地址:請點這裡
原文:http://blog.chmouel.com/2014/12/31/building-rpm-with-docker-images/ 作者: chmouel
譯文: http://dockerone.com/article/138## 譯者: 何林沖