为什么在Docker中使用完全相同的构建命令每次都会产生不同的哈希值?

时间:2018-04-21 13:43:51

标签: docker alpine

我正在CircleCI上构建一个简单的CI过程。它Dockerises一个WordPress实例,确定远程注册表是否有所得图像的副本,如果没有,则以特殊格式标记图像并将其推送。

但是,我在实践中发现图像始终不同,我已经将问题追溯到Docker文件的顶部,我称之为Alpine' s { {1}}命令。完整命令是:

apk

我在大约20分钟左右完成了两次构建,这个命令在每种情况下做了不同的事情。我开始使用Alpine 3.6中的固定哈希。

以下是倒数第二个版本的前几行:

RUN apk --update add git openssh-client

这是最新版本:

Step 1/42 : FROM alpine@sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106 AS build
sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106: Pulling from library/alpine

Digest: sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106
Status: Downloaded newer image for alpine@sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106
 ---> 77144d8c6bdc
Step 2/42 : RUN apk --update add git openssh-client
 ---> Running in 4dee205378ad
fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/community/x86_64/APKINDEX.tar.gz
(1/8) Installing ca-certificates (20161130-r2)
(2/8) Installing libssh2 (1.8.0-r1)
(3/8) Installing libcurl (7.59.0-r0)
(4/8) Installing expat (2.2.0-r1)
(5/8) Installing pcre (8.41-r0)
(6/8) Installing git (2.13.5-r0)
(7/8) Installing openssh-keygen (7.5_p1-r2)
(8/8) Installing openssh-client (7.5_p1-r2)
Executing busybox-1.26.2-r9.trigger
Executing ca-certificates-20161130-r2.trigger
OK: 28 MiB in 19 packages
 ---> 1c11addc5a9f
Removing intermediate container 4dee205378ad
Step 3/42 : WORKDIR /root
 ---> 0ec3661faedc
Removing intermediate container 3f0f8610abbc

为了方便读者,这里有一个图形差异:

Diff of Docker layer hashes

我的观点是,短暂的这种变化发生了太多次,因为对旧版本的Alpine进行了实际的操作系统更新(这是3.6,最新的是3.7)。我认为它可能是在更新中写入数据或时间戳,这对包管理器来说似乎是一件明智的事情。

但是,我希望在几分钟内创建的两个构建版本的哈希相同,除非有实际的操作系统更新。有人会在这里确认可能会发生什么,或解释我能做些什么来检查实际的变化?例如,是否有一种合理的方式可以对Docker图层进行区分?

如果Step 1/42 : FROM alpine@sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106 AS build sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106: Pulling from library/alpine Digest: sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106 Status: Downloaded newer image for alpine@sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106 ---> 77144d8c6bdc Step 2/42 : RUN apk --update add git openssh-client ---> Running in 8ad903516136 fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/community/x86_64/APKINDEX.tar.gz (1/8) Installing ca-certificates (20161130-r2) (2/8) Installing libssh2 (1.8.0-r1) (3/8) Installing libcurl (7.59.0-r0) (4/8) Installing expat (2.2.0-r1) (5/8) Installing pcre (8.41-r0) (6/8) Installing git (2.13.5-r0) (7/8) Installing openssh-keygen (7.5_p1-r2) (8/8) Installing openssh-client (7.5_p1-r2) Executing busybox-1.26.2-r9.trigger Executing ca-certificates-20161130-r2.trigger OK: 28 MiB in 19 packages ---> 4192a8ae6ba6 Removing intermediate container 8ad903516136 Step 3/42 : WORKDIR /root ---> 9f2a57c9923b Removing intermediate container 050a150cf83f 所做的更改永远不会完全重现,那么我是在我的注册表中创建固定基本映像的最佳解决方案,安装我需要的软件,并在其上构建?我必须设置一些东西来定期重建它(例如每隔几周)以获得安全更新,但如果它能让我获得稳定的构建层,那么这是可以接受的。

更新

我已将apk调用移到单独的构建中,现在我发现apk命令正在更改哈希值。

这是第一次运行:

sed

第二轮:

Step 15/39 : FROM registry.gitlab.com/username/jonblog-machine:latest
 ---> 5f854fc73292
Step 16/39 : RUN sed -i -r 's/memory_limit = \d+M/memory_limit = 30M/g' /etc/php7/php.ini
 ---> Running in d7205d0216f6
 ---> b64f045b6f51

这很令人困惑:我从两个Step 15/39 : FROM registry.gitlab.com/username/jonblog-machine:latest ---> 5f854fc73292 Step 16/39 : RUN sed -i -r 's/memory_limit = \d+M/memory_limit = 30M/g' /etc/php7/php.ini ---> Running in 152d628094ff ---> a397210c512b 开始,但步骤16每次都会产生一个新的哈希值。 (它从构建15开始,因为这是一个多阶段构建)。

我能做些什么来了解为什么我会得到不同的哈希?

1 个答案:

答案 0 :(得分:3)

图层哈希包含文件上的mtime时间戳,sed命令将更改。您可以在此处查看OCI图像的规范,其中docker紧随其后:

https://github.com/opencontainers/image-spec/blob/master/layer.md#file-attributes