Docker: 如何显示两个图像之间的差异

我有一个 Dockerfile,其中包含一系列执行“ apt-get install”的 RUN 指令; 例如,有几行:

RUN apt-get install -y tree
RUN apt-get install -y git

在执行了“ docker build”之后,如果执行“ docker images-a”,我将看到所有基础子元素的列表..。在构建过程中创建的图像。

我希望看到在执行“ apt-get install-y git”行时安装的所有软件包的列表(包括除了 git 软件包之外可能已经安装的依赖软件包)。

注意: 我相信“ docker diff”命令显示了容器和启动它的映像之间的区别。相反,我希望看到两个图像(相同谱系)之间的区别: “ tree”和“ git”图像 ID。这可能吗?

谢谢。

73314 次浏览

每个 RUN 指令创建一个新的容器,您可以使用 docker diff <container>检查容器更改了什么。

因此,在构建您的 dockerfile 之后,运行 docker ps -a以获得构建文件创建的容器列表。它应该是这样的:

CONTAINER ID  IMAGE        COMMAND               CREATED        STATUS ...
53d7dadafee7  f71e394eb0fc /bin/sh -c apt-get i  7 minutes ago  Exit 0 ...
...

现在您可以执行 docker diff 53d7dadafee7来查看更改了什么。

我想您可以通过 docker export CONTAINER_IDdocker save IMAGE_ID(根据注释更新)将这两个图像的文件系统发送到 tarball

然后使用任何你喜欢的工具来区分文件系统-Git,Rdiff,等等。

如果您知道容器 ID 或名称(甚至已停止的容器) , 您可以快速转储文件列表的动态。

$ docker export CONTAIN_ID_OR_NAME | tar tv
-rwxr-xr-x  0 0      0           0  2  6 21:22 .dockerenv
-rwxr-xr-x  0 0      0           0  2  6 21:22 .dockerinit
drwxr-xr-x  0 0      0           0 10 21 13:46 bin/
-rwxr-xr-x  0 0      0     1021112 10  8  2014 bin/bash
-rwxr-xr-x  0 0      0       31152 10 21  2013 bin/bunzip2
-rwxr-xr-x  0 0      0           0 10 21  2013 bin/bzcat link to bin/bunzip2
lrwxrwxrwx  0 0      0           0 10 21  2013 bin/bzcmp -> bzdiff
-rwxr-xr-x  0 0      0        2140 10 21  2013 bin/bzdiff
lrwxrwxrwx  0 0      0           0 10 21  2013 bin/bzegrep -> bzgrep
-rwxr-xr-x  0 0      0        4877 10 21  2013 bin/bzexe
......

然后,您可以保存列表文件和比较太列表文件。

如果你坚持使用图片 ID 或者名字,你可以在飞行中丢弃 第一层的文件列表:

$ docker save alpine |tar xO '*/layer.tar' | tar tv
drwxr-xr-x  0 0      0           0 12 27 06:32 bin/
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/ash -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/base64 -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/bbconfig -> /bin/busybox
-rwxr-xr-x  0 0      0      821408 10 27 01:15 bin/busybox

毕竟,我建议您启动容器,然后停止它,然后您可以得到一个合并的文件列表,如第一种方式所述。

2017年2月1日:

# PID=$(docker inspect -f '\{\{.State.Pid}}' CONTAIN_ID_OR_NAME)
# cd /proc/$PID/root && ls -lF
drwxr-xr-x  0 0      0           0 12 27 06:32 bin/
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/ash -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/base64 -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/bbconfig -> /bin/busybox
-rwxr-xr-x  0 0      0      821408 10 27 01:15 bin/busybox

注意,如果您正在使用 docker-machine,则需要首先通过 然后是 sudo sh

现在您得到了两个容器的根目录,您可以使用 diff 直接比较它们。

看看这个:

Https://github.com/moul/docker-diff

他们列出了 Mac 的 Brew安装说明,我假设它是一个 Bash 脚本,所以我假设它可以在其他 * nix 环境中工作。

看看这个:

Https://github.com/googlecloudplatform/container-diff

这个工具可以区分本地或远程 Docker 映像,并且不需要安装 docker。它具有文件和包级别“不同”(例如: apt、 npm 和 pip) ,因此您可以更容易地看到两个 Docker 映像之间更改的包的差异。

免责声明: 我是这个项目的贡献者

这个对我很管用:

docker run -it e5cba87ecd29 bash -c 'find /path/to/files -type f | sort  | xargs -I{} sha512sum {}' > /tmp/dockerfiles.e5cba87ecd29.txt
docker run -it b1d19fe1a941 bash -c 'find /path/to/files -type f | sort  | xargs -I{} sha512sum {}' > /tmp/dockerfiles.b1d19fe1a941.txt
meld /tmp/dockerfiles*

其中 e5cba87ecd29和 b1d19fe1a941是我感兴趣的图像,而/path/to/files 是一个可以是“/”的目录。 它列出所有的文件,排序,并添加散列到它只是为了以防万一。

现在是2019年,我刚刚发现了一个有用的工具,它是在2017年末发布的。 Https://opensource.googleblog.com/2017/11/container-diff-for-comparing-container-images.html

以下内容来自 容器差速器 github 页面:

container-diff diff <img1> <img2> --type=history  [History]
container-diff diff <img1> <img2> --type=file  [File System]
container-diff diff <img1> <img2> --type=size  [Size]
container-diff diff <img1> <img2> --type=rpm  [RPM]
container-diff diff <img1> <img2> --type=pip  [Pip]
container-diff diff <img1> <img2> --type=apt  [Apt]
container-diff diff <img1> <img2> --type=node  [Node]

类似地,您可以同时运行多个分析程序:

container-diff diff <img1> <img2> --type=history --type=apt --type=node

在这种情况下,似乎你只需要看到两层之间的区别。如果是这样的话,dive在这方面是非常棒的; 它允许您检查每一层的文件系统,并且您可以通过更改类型(不变、添加、删除、修改)来过滤文件。

如果您想检查两个不相关的图像之间的差异,让两个 dive进程并排运行也可以。