mlj*_*jrg 6 docker docker-image
我们如何确定两个Docker映像具有完全相同的文件系统结构,并且无论文件时间戳如何,相应文件的内容都相同?
我尝试了映像ID,但是在使用相同的Dockerfile和干净的本地存储库进行构建时,它们会有所不同。我通过构建一个图像,清理本地存储库,然后触摸其中一个文件以更改其修改日期,然后构建第二个图像以及它们的图像ID不匹配来进行此测试。我使用了Docker 17.06(我相信是最新版本)。
如果要比较图像的内容,可以使用docker inspect <imageName>
命令,然后查看RootFS部分
docker inspect redis
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:eda7136a91b7b4ba57aee64509b42bda59e630afcb2b63482d1b3341bf6e2bbb",
"sha256:c4c228cb4e20c84a0e268dda4ba36eea3c3b1e34c239126b6ee63de430720635",
"sha256:e7ec07c2297f9507eeaccc02b0148dae0a3a473adec4ab8ec1cbaacde62928d9",
"sha256:38e87cc81b6bed0c57f650d88ed8939aa71140b289a183ae158f1fa8e0de3ca8",
"sha256:d0f537e75fa6bdad0df5f844c7854dc8f6631ff292eb53dc41e897bc453c3f11",
"sha256:28caa9731d5da4265bad76fc67e6be12dfb2f5598c95a0c0d284a9a2443932bc"
]
}
Run Code Online (Sandbox Code Playgroud)
如果所有图层都相同,则图像包含相同内容
经过一些研究,我想出了一个根据我的测试快速而干净的解决方案。
整体解决方案是这样的:
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; }
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
3) 现在 invoke ./md5docker <image>
,其中<image>
是您的图像名称或 ID,以计算图像的整个文件系统的 MD5 哈希值。
要验证两个图像是否具有相同的内容,只需检查它们的哈希值是否与步骤 3 中计算的相同)。
请注意,此解决方案仅考虑内容目录结构、常规文件内容和符号链接(软和硬)。如果您需要更多,只需tarcat
通过添加更多elif
测试您希望包含的内容的子句来更改脚本(请参阅Python 的 tarfile,并查找TarInfo.isXXX()
与所需内容相对应的方法)。
我在这个解决方案中看到的唯一限制是它对 Python 的依赖(我使用的是 Python3,但它应该很容易适应 Python2)。一个没有任何依赖的更好的解决方案,而且可能更快(嘿,这已经非常快了),是tarcat
用一种支持静态链接的语言编写脚本,这样一个独立的可执行文件就足够了(即,不需要任何外部依赖,但是唯一的操作系统)。我把它留作 C、Rust、OCaml、Haskell 的未来练习,你选择。
请注意,如果 MD5 不适合您的需要,只需将md5
第一个脚本内部替换为您的哈希实用程序。
希望这对任何阅读的人都有帮助。
让我惊讶的是 docker 并没有开箱即用地做这种事情。这是@mljrg 技术的一个变体:
#!/bin/sh
docker create $1 | {
read cid
docker export $cid | tar Oxv 2>&1 | shasum -a 256
docker rm $cid > /dev/null
}
Run Code Online (Sandbox Code Playgroud)
它更短,根本不需要 python 依赖项或第二个脚本,我确定有缺点,但它似乎对我进行了一些测试。
归档时间: |
|
查看次数: |
2918 次 |
最近记录: |