如何确定性地构建 Docker 镜像?

Pat*_*Huy 5 docker

我正在尝试构建 Docker 映像,并且希望我的 Docker 映像具有确定性。令我惊讶的是,我发现即使是一个简单的 Dockerfile,例如

FROM scratch
ENV a b
Run Code Online (Sandbox Code Playgroud)

重复使用时生成不同的 IDdocker build --no-cache .

如何使我的构建具有确定性以及导致图像 ID 发生变化的原因是什么?启用缓存后,会生成相同的 ID。

我试图获得这种可重复性的原因是为了能够在分布式构建环境中生成相同的层。我无法控制构建的运行位置,因此我无法知道缓存中的内容。另外,Docker 构建使用 wget 从 ftp 下载文件,这些文件可能已更改,也可能未更改,目前我无法轻松地从 Dockerfile 中告诉 Docker a 的结果是否RUN应使缓存无效。因此,如果我可以为相同的层生成相同的 ID(当不使用缓存时),这些层就不必再次“推”和“拉”。

还有这里列出的所有原因:https ://reproducible-builds.org/

Deu*_*ina 5

AFAIK,目前 docker 镜像不会哈希到字节精确的哈希值,因为元数据当前包含状态信息,例如创建日期。您可以查看1.10 的设计文档。不幸的是,历史元数据似乎是图像有效性和识别的重要组成部分。

不要误会我的意思,我只关心可复制的构建。然而,我不认为哈希精确性是衡量 Docker 镜像可重复性的最佳标准。docker 映像不是编译的二进制文件。无法保证阶段的结果能够被重现,因此即使日期时间元数据不存在,也不能保证可重现的构建。举这个病态的例子:

RUN curl "https://www.random.org/strings/?num=1&len=20&digits=on&unique=on&format=plain&rnd=new" -o nonce.txt
Run Code Online (Sandbox Code Playgroud)

  • 哈希准确性的好处是它意味着其他形式的准确性并且很容易测试。与所说的“相同行为”相比,这有时是一个令人犹豫的问题! (4认同)
  • 恰恰。Docker 镜像是“支持”可重复性的一种方式。它们更可移植(比本地编译)、更少耦合(比系统动态链接库)、更可重现,但它们不是绝对可移植、解耦或可重现的,因为就像你说的,这需要定义绝对行为,这是一个不完整的解决问题:p (2认同)
  • 哈哈,“在本文中,我们通过证明图灵机上的相同程序产生相同的输出来解决停止问题的受限变体”:) (2认同)