我们如何确定两个Docker镜像具有完全相同的文件系统结构,并且相应文件的内容是否相同,与文件时间戳无关?
我尝试了图片ID,但是在使用相同的Dockerfile和干净的本地存储库构建时它们有所不同:我通过构建一个图像,清理本地存储库,然后触摸其中一个文件以更改其修改日期来进行此测试,然后构建第二个图像,它们的图像ID不匹配。我使用的是Docker 17.06(我相信的最新版本)。
由于
答案 0 :(得分:3)
如果要比较图像内容,可以使用docker inspect <imageName>
命令,可以查看RootFS部分
docker inspect redis
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:eda7136a91b7b4ba57aee64509b42bda59e630afcb2b63482d1b3341bf6e2bbb",
"sha256:c4c228cb4e20c84a0e268dda4ba36eea3c3b1e34c239126b6ee63de430720635",
"sha256:e7ec07c2297f9507eeaccc02b0148dae0a3a473adec4ab8ec1cbaacde62928d9",
"sha256:38e87cc81b6bed0c57f650d88ed8939aa71140b289a183ae158f1fa8e0de3ca8",
"sha256:d0f537e75fa6bdad0df5f844c7854dc8f6631ff292eb53dc41e897bc453c3f11",
"sha256:28caa9731d5da4265bad76fc67e6be12dfb2f5598c95a0c0d284a9a2443932bc"
]
}
如果所有图层都相同,则图像包含相同的内容
答案 1 :(得分:3)
整体解决方案是:
docker create ...
docker export ...
就是这样。
从技术上讲,这可以通过以下方式完成:
1)创建文件md5docker
,并赋予其执行权限,例如chmod +x md5docker
:
#!/bin/sh
dir=$(dirname "$0")
docker create $1 | { read cid; docker export $cid | $dir/tarcat | md5; docker rm $cid > /dev/null; }
2)创建文件tarcat
,并赋予其执行权限,例如chmod +x tarcat
:
#!/usr/bin/env python3
# coding=utf-8
if __name__ == '__main__':
import sys
import tarfile
with tarfile.open(fileobj=sys.stdin.buffer, mode="r|*") as tar:
for tarinfo in tar:
if tarinfo.isfile():
print(tarinfo.name, flush=True)
with tar.extractfile(tarinfo) as file:
sys.stdout.buffer.write(file.read())
elif tarinfo.isdir():
print(tarinfo.name, flush=True)
elif tarinfo.issym() or tarinfo.islnk():
print(tarinfo.name, flush=True)
print(tarinfo.linkname, flush=True)
else:
print("\33[0;31mIGNORING:\33[0m ", tarinfo.name, file=sys.stderr)
3)现在调用./md5docker <image>
,其中<image>
是您的图片名称或ID,以计算图片整个文件系统的MD5哈希值。
要验证两个图像是否具有相同的内容,只需检查它们的哈希值是否与步骤3中计算的相同。
请注意,此解决方案仅考虑内容目录结构,常规文件内容和符号链接(软和硬)。如果您还需要更多内容,只需更改tarcat
脚本,为您要包含的内容添加更多elif
条款测试(请参阅Python's tarfile,并查找与此相对应的方法TarInfo.isXXX()
需要的内容)。
我在这个解决方案中看到的唯一限制是它对Python的依赖(我使用Python3,但它应该很容易适应Python2)。一个没有任何依赖的更好的解决方案,可能更快(嘿,这已经非常快),是用支持静态链接的语言编写tarcat
脚本,这样一个独立的可执行文件就足够了(即,一个不需要任何外部依赖,但唯一的OS)。我把这作为C,Rust,OCaml,Haskell的未来练习,你选择。
注意,如果MD5不符合您的需求,只需使用您的哈希实用程序替换第一个脚本中的md5
。
希望这有助于任何人阅读。
答案 2 :(得分:1)
似乎没有一种标准的方法可以做到这一点。我能想到的最好的方法是使用Docker多级构建功能。 例如,我在这里比较apline和debian图像。在您的情况下,将图像名称设置为您要比较的图像名称
我基本上将每个图像中的所有文件复制到git存储库中,并在每次复制后提交。
FROM alpine as image1
FROM debian as image2
FROM ubuntu
RUN apt-get update && apt-get install -y git
RUN git config --global user.email "you@example.com" &&\
git config --global user.name "Your Name"
RUN mkdir images
WORKDIR images
RUN git init
COPY --from=image1 / .
RUN git add . && git commit -m "image1"
COPY --from=image2 / .
RUN git add . && git commit -m "image2"
CMD tail > /dev/null
这将为您提供一个带有git存储库的图像,该存储库记录两个图像之间的差异。
docker build -t compare .
docker run -it compare bash
现在,如果您执行git log
,您可以看到日志,并且可以使用git diff <commit1> <commit2>
注意:如果图像构建在第二次提交时失败,这意味着图像是相同的,因为如果没有提交更改,git提交将失败。
答案 3 :(得分:0)
让我惊讶的是,docker并没有开箱即用。这是@mljrg技术的一种变体:
#!/bin/sh
docker create $1 | {
read cid
docker export $cid | tar Oxv 2>&1 | shasum -a 256
docker rm $cid > /dev/null
}
它更短,根本不需要python依赖项或第二个脚本,我敢肯定有缺点,但是它对我完成的一些测试似乎很有效。