当前位置: 移动技术网 > 科技>操作系统>windows > 创建RPM包的同时构建Docker镜像的方法

创建RPM包的同时构建Docker镜像的方法

2018年03月08日  | 移动技术网科技  | 我要评论

河蚌的呼吸器官,李逵的绰号,人民日报电子版

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或者别的容器技术抽象而来的系统来完成打包工作)的话,我想会更好。

由于我的项目还没有完成,所以我只是对我的想法进行了验证:简单构建一个包含依赖的镜像。

这是一个使用生成版本 的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/bash
set -exf
project=myproject</p> <p>curdir=$(dirname $(readlink -f $0))
topdir=$(git rev-parse --show-topklevel 2>/dev/null)</p> <p>rm -rf ${curdir}/.build/rpm
mkdir -p ${curdir}/.build/rpm/{build,srpms,specs,rpms/noarch}
cp -r ${curdir}/sources ${curdir}/.build/rpm</p> <p>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</p> <p>sed -e "s/%define _version.*/%define _version ${saladier_version}/" ${curdir}/specs/${myroject}.spec > \
${curdir}/.build/rpm/specs/${myproject}.spec</p> <p>docker build -t chmouel/buildrpm ${curdir}
docker run -v $curdir/.build:/data -it chmouel/buildrpm</p> <p>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 <chmouel@enovance.com></p> <p>run yum -y groupinstall 'development tools'
run yum -y install fedora-packager
run yum -y install yum-utils</p> <p>run yum -y install sudo
run sed -i.bak -n -e '/^defaults.*requiretty/ { s/^/# /;};/^%wheel.*all$/ { s/^/# / ;} ;/^#.*wheel.*nopasswd/ { s/^#[ ]*//;};p' /etc/sudoers</p> <p>run yum install -y https://rdo.fedorapeople.org/rdo-release.rpm</p> <p># 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</p> <p>add bin/start.sh /start.sh</p> <p>run useradd -s /bin/bash -g adm,wheel,systemd-journal -m rpm</p> <p>workdir /home/rpm
cmd /start.sh</p> <p>add .build/rpm/ /home/rpm/rpmbuild/
run chown -r rpm: /home/rpm</p> <p>user rpm

以及从容器中运行的start.sh脚本:


复制代码
代码如下:
#!/bin/bash
# script run inside the container
rpmbuild -ba rpmbuild/specs/project.spec || exit 1</p> <p>[[ -d /data ]] || exit 0</p> <p>sudo rm -rf /data/output
sudo cp -a rpmbuild/rpms/noarch /data/output

脚本可能无法直接在你的环境中使用,但至少能让你了解这个idea。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网