经过一些研究,我想出了一个解决方案,根据我的测试,它既快速又干净。
整体解决方案是这样的:
- 通过
docker create ...为您的图像创建一个容器
- 通过
docker export ... 将其整个文件系统导出到 tar 存档
- 将存档目录名称、符号链接名称、符号链接内容、文件名和文件内容通过管道传输到哈希函数(例如 MD5)
- 比较不同图像的哈希值以验证它们的内容是否相等
就是这样。
从技术上讲,这可以通过以下方式完成:
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 脚本,这样一个独立的可执行文件就足够了(即,一个不需要任何外部依赖项,但唯一的操作系统)。我把它留作 C、Rust、OCaml、Haskell 的未来练习,你可以选择。
注意,如果 MD5 不适合您的需要,只需将第一个脚本中的 md5 替换为您的哈希实用程序即可。
希望这对阅读的人有所帮助。