内容简介:我最近正在开展一个小项目,学习使用Docker工具链,并了解其工作原理。 我决定构建(又一个)首先阐述我的要求:第一个挑战是建立一个自动化流程来构建新镜像并将其上传到Docker Hub。 有一篇
我最近正在开展一个小项目,学习使用 Docker 工具链,并了解其工作原理。 我决定构建(又一个) etcd 的开源Docker镜像并将其发布在Docker Hub上。 像所有开源项目一样,构建一个有效的Docker镜像非常简单,并没有花太多时间。反而是如何镜像让更多人觉得有用会花费更多的时间。 在这个过程中,我学到了一些关于使用 Docker , Docker Hub 和 Travis 的内容,但仍然有一些问题没有得到解答。 因此,我认为值得记录我的发现和未解答的问题,以获得反馈并提高我的理解。
首先阐述我的要求:
- 支持最新版本和一些旧版本的应用程序似乎是Docker社区中的常见做法。 支持常见发行版及其精简版本似乎也是一种常见做法。 因此,该镜像应该遵循社区的做法。
- Github上的README自动同步到Docker Hub上的描述是必须的。 我的假设是开发人员通常会在Docker Hub上发现Docker镜像。 所以只在Github上有一个很好的自述文件是不够的。 该文档也必须存在于Docker Hub上。 我不想在我的git仓库中编写文档,然后每次有更改时手动将其复制到Docker Hub。
- 镜像本身应该非常易于使用,既可以作为服务器运行etcd,也可以作为CLI客户端运行。 我不打算讨论这个,因为这与本章主题有点无关。 但是如果你感兴趣的话,请查看 README 并在Github项目中打开一个issue来反馈问题。
第一个挑战是建立一个自动化流程来构建新镜像并将其上传到Docker Hub。 有一篇 很好的博客 记录了如何使用Travis实现这一目标,以便每次推送到代码库都会构建一个新镜像像,并且当合并分支时,构建的新镜像将被推送到Docker Hub。 设置很简单。
尽管简单,但它不符合我的任何要求。 下面尝试逐一解决。
问题#1 - 自动同步README
虽然上面提及到的Travis构建过程可以构建并将镜像推送到Docker Hub,但它无法同步README。 Docker CLI也不支持更新Docker Hub上的描述。
Docker Hub有一个名为 Automated Builds 的东西,通过配置,可以达到Travis作业产生的结果。 并且,它还可以从Github仓库中提取README的内容,以便在Docker Hub上作为描述使用。 因此,我们可以使用Automated Builds来构建镜像并从Github同步README。 这解决了我们的一项要求。
Automated Builds的工作原理是我们必须在Docker Hub上配置它以指定Docker上下文的路径(即Dockerfile的路径),从该Dockerfile构建镜像并打上自己的标记。 这意味着从仓库构建的每个镜像,必须在唯一路径上存在Dockerfile。 这很快就会成为一个问题。
问题#2 - 运行测试
虽然Docker Hub上的Automated Builds解决了README同步问题,但自动构建还存在一些其他问题。 你无法将其用作运行测试和获取PR测试状态的工具。 根本没有办法从Docker Hub的构建系统获得反馈给Github。 这对于开发流程至关重要
所以有一件事是肯定的 - 如果构建失败,我们需要回到Travis运行测试并阻止PR。
问题#3 - 为多个版本构建镜像
我不仅想构建etcd的最新版本,也包括之前的一些版本,并构建这些版本的发行版本。
支持的版本:
3.3(最新)
3.2
支持的发行版本:
Debian:stretch-slim
alpine
因此,我们必须构建总共4个镜像 - 每个发行版本对应一个版本。
首先看看多版本问题。
我开始查看其他开源Docker镜像是如何实现这一点的。 结果并不令人满意。
看了 MySQL 镜像的Dockerfiles。 每个版本的MySQL的docker镜像都在仓库的“版本目录”中有一个专用的Dockerfile。 他们几乎没有区别。 请参阅这两个MySQL的Dockerfiles - MySQL 5.6 和 MySQL 5.7 的Dockerfile。 在76行代码中,它们只有一行不同,并且只是版本不同。
我在 Nginx的Dockerfiles 中观察到了一个非常相似的模式。 平均而言,每个Dockerfile中每个基本镜像的每个版本只有5-10%的行不同。
这看起来像是大量的重复代码。 我不想这样,因为每个镜像中唯一不同的是版本和包管理器(Alpine和Debian使用不同的包管理器)。
Dockerfile的ARG 可用于简化此操作。 通过将值传递给docker build命令,ARG可用于定义在构建镜像时可以设置的变量。 这非常方便。 由于每个版本的Dockerfiles唯一不同的是 URL中的版本本身 ,我可以轻松地使用它并使用相同的Dockerfile和以下命令为不同版本构建docker镜像:
docker build . -t "3.3" --build-arg version=3.3 docker build . -t "3.2" --build-arg version=3.2
在带有环境矩阵的Travis中使用它,我们可以自动为多个版本构建Docker镜像。 请参阅.travis.yml中为每个版本构建多个镜像的代码段:
language: bash services: docker env: matrix: - VERSION=3.3.1 - VERSION=3.2.19 script: - docker build . -t "$VERSION" --build-arg version=$VERSION
这解决了多版本的多镜像问题。 但我们仍然需要解决为每个版本的每个基本镜像构建镜像的问题。
问题#4 - 为多个基本镜像进行构建
除了为多个版本构建镜像,我们还存在为多个基本镜像构建镜像的问题。 现在仅仅使用ARG是不够的。
在这种情况下,挑战变成了每个发行版可能都有自己的具体操作方式,例如包管理。 Alpine和Debian使用不同的包管理器。 因此仅使用ARG不足以处理所有更改。 还需要管理如何进行包的安装。 在这种情况下,我们需要一个安装包,但不需要运行etcd。 如果我们能够以某种方式获得没有任何额外的etcd二进制文件,我们就可以制作出完美的Docker镜像。
多阶段Docker构建和构建器模式
Docker的Multi-Stage Builds 是一种干净利落地构建Docker镜像的方式。 通常在构建过程中,我们会安装大量随机包。 成功构建应用程序后,清理可能会很麻烦。
构建Docker镜像时,镜像总是越小越好。 有些人使用bash脚本编写清理指令。 有些人将开发和生产Dockerfiles分开,开发Dockerfile会产生一个较大包体的镜像,其包含开发所需的一切,生产Dockerfile会生成一个仅具有开发Docker镜像所必需工件的docker镜像。 但这两种方法都有各自的不足。
多阶段构建简化了其中的一部分,并提供了更好地组织Dockerfiles的方法。 你可以在Dockerfiles中添加多个阶段,为每个阶段构建一个完全独立的Docker镜像,并使用其他构造可以轻松地将工件从一个阶段复制到另一个阶段。 从Docker Hub上的文档中查看此示例:
FROM golang:1.7.3 WORKDIR /go/src/github.com/alexellis/href-counter/ RUN go get -d -v golang.org/x/net/html COPY app.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=0 /go/src/github.com/alexellis/href-counter/app . CMD ["./app"]
首先,注意这个Dockerifle有多个FROM指令。 每条指令表示不同的构建阶段,从而产生完全不同的镜像。 COPY指令采用名为--from的参数,可用于从其他构建阶段复制文件。 使用此选项来复制你想要用来构建镜像的文件,并留下不需要的所有内容。
多阶段构建与ARG结合可以解决我们的问题。 现在可以同时使用version和base_image,并使用base_image和FROM指令在构建时选择基本镜像。
FROM debian:stretch-slim ... FROM "$base_image" ... COPY --from=0 /path/to/etcd-binary /usr/local/bin CMD ["etcd"]
然后运行以下命令来构建所有的镜像:
# Version 3.3 on debian:stretch-slim docker build . -t "3.3" --build-arg version=3.3 \ --build-arg base_image="debian:stretch-slim" # Version 3.3 on alpine:latest docker build . -t "3.3:alpine" --build-arg version=3.3 \ --build-arg base_image="alpine:latest" # Version 3.2 on debian:stretch-slim docker build . -t "3.2" --build-arg version=3.2 \ --build-arg base_image="debian:stretch-slim" # Version 3.2 on alpine:latest docker build . -t "3.2:alpine" --build-arg version=3.2 \ --build-arg base_image="alpine:latest"
在这里查看 完整的Dockerfile 。
这为我们解决为多版本构建镜像和多个基本镜像代码重复的问题。
Multi-Stage Builds有一些很酷的功能。 我建议检查一下,以获得更好的Docker体验。
有了这个,可以通过 环境构建矩阵 提供的不同环境来构建在Travis上的所有镜像,在每个环境合并代码到主分支,构建镜像、运行测试、推送构建好的镜像到Docker Hub。 这是一个示例.travis.yml文件(上一个示例的扩展):
language: bash services: docker env: matrix: - VERSION=3.3.1 BASE_IMAGE=debian:stretch-slim - VERSION=3.2.19 BASE_IMAGE=debian:stretch-slim - VERSION=3.3.1 BASE_IMAGE=alpine - VERSION=3.2.19 BASE_IMAGE=alpine script: - | docker build . -t "$VERSION" \ --build-arg version=$VERSION \ --build-arg base_image="$BASE_IMAGE"
但同步README的问题仍然存在,并且Travis似乎也无法做到。 下面看看如何解决。
问题#5 - 捆绑在一起
我们在这里取得了以下进展:
- 我们知道如何为每个版本和每个基本镜像构建Docker镜像。 可用一种可管理的方式执行此操作,而无需重复代码。 并且可以在Travis上进行构建。
- 可以在Travis上构建镜像并推送到Docker。 但是无法在Docker Hub上获得README。
- 可以使用Automated Builds在Docker Hub上构建镜像,并将README同步到Docker Hub。 但是我们无法为Github上的每个pull请求构建镜像,并且如果构建失败则阻止合并pull请求。 并且不会给Github任何反馈。
因此,虽然我们可以使用Travis构建所有镜像并为每个PR运行测试,但无法使用它来推送镜像。 而对于Docker Hub则相反。 实际上,最简单形式的Docker Hub的Automated Build系统不能用于基于ARG的设置,因为Automated Builds可以使用Docker上下文,即在构建设置中为“每个指定的路径”构建镜像,并期望这些路径中存在Dockerfile。 你无法在此类设置中传递CLI参数。 因此,我们的自定义docker构建命令不适用于Automated Builds。
自定义构建阶段钩子,用于Docker Hub上的自动构建
自定义构建阶段钩子允许在不同的构建阶段执行自定义脚本,从而对自动构建进行更高级的自定义。 例如,可以覆盖构建阶段以将额外参数传递给docker构建,或者可以覆盖推送阶段以推送到多个仓库。 当然,你还可以做很多事情。
这最终解决了我们所有的问题:
- 我们可以使用Travis设置为每个PR构建和运行测试,但不能将镜像推送到Docker Hub。
- 只能在主分支上使用自动构建和自定义阶段钩子。 这将把我们的镜像推送到Docker Hub并同步来自Github的README。
构建钩子脚本是很通用的。 我参考在Travis中构建镜像的脚本来编写钩子脚本!
在此处查看整个设置:
结论
没有重复代码,易于构建的过程,良好的开发体验和README的自动同步 - 这对我来说非常有用,我对最终的设置非常满意。
有人可能会说使用Docker Automated Build和Travis很难维护。 可以通过自定义构建钩子将PR状态推送到Github,但这不是我到目前为止所探讨的,与在Docker Hub上维护Travis和Automated Builds相比,它看起来也需要更多精力。
但有一件事不确定是使用ARG构建Docker镜像的方法和多阶段构建。 虽然它适合我,但我在这个领域的经验是有限的,我想得到反馈。 你怎么看? 还有构建和分发开源Docker镜像更好的方法吗? 请通过评论部分告诉我你的想法。
以上所述就是小编给大家介绍的《使用Travis在Docker Hub上管理开源Docker镜像》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用 tunasync 搭建开源镜像站
- 清华大学开源软件镜像站推出一键使用服务
- Anaconda 恢复清华大学开源软件镜像,近期服务上线
- Composer 中国全量镜像开源了,一起让 PHP 社区更繁荣
- Composer 中国全量镜像开源了,一起让 PHP 社区更繁荣
- 大规模集群中 Docker 镜像如何分发管理?试试 Uber 刚开源的 Kraken
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5秘籍(第2版)
[美] Matthew MacDonald / 李松峰、朱巍、刘帅 / 人民邮电出版社 / 2015-4 / 89.00元
不依赖插件添加音频和视频,构建适用于所有浏览器的播放页面。 用Canvas创建吸引人的视觉效果,绘制图形、图像、文本,播放动画,运行交互游戏。 用CSS3将页面变活泼,比如添加新奇的字体,利用变换和动画添加吸引人的效果。 设计更出色的Web表单,利用HTML5新增的表单元素更加高效地收集访客信息。 一次开发,多平台运行,实现响应式设计,创建适配桌面计算机、平板电脑和智能手机......一起来看看 《HTML5秘籍(第2版)》 这本书的介绍吧!