当前位置: 首页 > news >正文

使用Docker镜像构建RPM包

本文讲的是使用Docker镜像构建RPM包, 【编者的话】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/bash
set -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 <chmouel@enovance.com>

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。

原文链接: Building RPM with Docker images (翻译:何林冲 审校:李颖杰)

原文发布时间为:2015-01-13 
本文作者:何林冲
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:使用Docker镜像构建RPM包

相关文章:

  • oracle存储过程例子及其他语句[1]
  • 把问题描述清楚是解决问题的起点
  • jquery:利用jsonp跨域访问--转载
  • async await
  • 《C#本质论》读书笔记(十)异常处理 @ Lennon
  • xml 转义特殊字符
  • openldap+php-ldap操作
  • 人生的二和三
  • Springmvc----注解和非注解开发
  • js 获取URL参数的值
  • 想要Freestyle?先要遵守 MySQL 这十大铁律!
  • 一位女程序员的征婚广告
  • 高通和诺基亚携手推动5G新空口大规模移动部署
  • 8月6日中国概念股涨跌互现 dj97跌6.56%
  • 关于 Cirru Editor 存储格式
  • 【Leetcode】101. 对称二叉树
  • Android组件 - 收藏集 - 掘金
  • JavaScript-Array类型
  • JAVA之继承和多态
  • oldjun 检测网站的经验
  • PHP CLI应用的调试原理
  • Python十分钟制作属于你自己的个性logo
  • Redis 中的布隆过滤器
  • SpiderData 2019年2月13日 DApp数据排行榜
  • WePY 在小程序性能调优上做出的探究
  • 从tcpdump抓包看TCP/IP协议
  • 电商搜索引擎的架构设计和性能优化
  • 分享一份非常强势的Android面试题
  • 力扣(LeetCode)21
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 浅谈Golang中select的用法
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 使用parted解决大于2T的磁盘分区
  • 携程小程序初体验
  • 一份游戏开发学习路线
  • 主流的CSS水平和垂直居中技术大全
  • #include<初见C语言之指针(5)>
  • (12)Linux 常见的三种进程状态
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (二)pulsar安装在独立的docker中,python测试
  • (九)One-Wire总线-DS18B20
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (三) diretfbrc详解
  • (生成器)yield与(迭代器)generator
  • (十八)三元表达式和列表解析
  • (一)80c52学习之旅-起始篇
  • (转)linux下的时间函数使用
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .libPaths()设置包加载目录
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET(C#) Internals: as a developer, .net framework in my eyes