在 Docker Engine 29.8.2(containerd 镜像存储)里实测镜像的 tag、ID 与 digest:镜像 ID 就是顶层 manifest 摘要;docker tag 挪走名字后旧镜像变成 untagged(无名字)但仍可按 ID 运行,docker build 同名则直接替换;同一个 Dockerfile 的 --no-cache 两次构建 ID 不同;全缓存重复构建默认也得到 3 个不同的 ID,关掉 provenance 后三次一致。
在 Docker Engine 29.8.2 里把一个 8 条指令的镜像 docker save 出来,逐层读 OCI 结构:5 个 blob(1 manifest + 1 config + 3 层)文件名都等于内容的 sha256;config 里 history 9 条、6 条没有层;每层的 digest(压缩数据)与 config.rootfs.diff_ids(解压 tar)是两个不同的 sha256,都能重新算出来。
在本机 registry:2 上实测 docker push / pull 的 HTTP 请求:push 是 14 个请求(4 个 blob 先 HEAD 404、再 POST+PUT 上传,最后才 PUT manifest);本地还有层时 pull 只发 1 个 HEAD;从零拉取手工上传的镜像是 HEAD manifest、GET manifest(按摘要)、GET 两个 blob 共 4 个请求;registry 的 Accept 头不匹配时 manifest 返回 404。
在本机 registry:2 上实测自建仓库的推送与回收:默认 DELETE manifest 返回 405,开启 REGISTRY_STORAGE_DELETE_ENABLED 后返回 202 但磁盘几乎没变(8352 → 8320 KB),要 garbage-collect 才回收(8320 → 6248 KB,7 → 4 个 blob 文件);不同仓库之间推送共享层时直接 Mounted from。
在 Docker Engine 29.8.2 里实测镜像的导出与导入:docker save 的 tar 是 4518 KB(压缩内容,而 inspect 的 Size 是 14290 KB);rmi 后 docker load 得到相同的镜像 ID;两个共用基础层的镜像一起 save 比分开少 4001 KB;docker export / import 会把镜像压成 1 层并丢掉 Env 和 Cmd。
在 Docker Engine 29.8.2 里实测层共享的磁盘占用:3 个镜像共用一个 55.5MB 的基础镜像,每个的 SIZE 都是 57.6MB(SHARED 55.53MB、UNIQUE 2.104MB),四个 SIZE 相加 228.3MB,而基础加三个 UNIQUE 只有 61.8MB;删掉基础镜像的名字不影响子镜像。
进到 Docker Desktop 的虚拟机里实测容器的 overlay 挂载:这个 Docker 用 containerd 的 overlayfs snapshotter(不是 overlay2),4 层镜像的容器有 5 个 lowerdir(多出一个容器创建时的层:hostname、resolv.conf、hosts 等),upperdir 初始为空,新建和修改的文件落在 upperdir,docker rm 后 upperdir 随之删除而镜像层仍在。
在 Docker Desktop 里实测 OverlayFS 的 copy-up:镜像里 128 MiB 的文件,容器里第一次追加 1 字节要 155.0~2174.1 ms(3 次),之后追加约 0 ms;只 chmod 也要 179.6~862.0 ms;upperdir 里是整个文件的拷贝;放在 volume 里的同样文件追加 0.0 ms。
进入 Docker Desktop 虚拟机实测 OverlayFS 的删除:删除镜像里的文件会在 upperdir 里留下 0:0 的字符设备(whiteout),删除又重建的目录带 trusted.overlay.opaque=y,删除再同名重建的文件是普通文件;docker commit 之后镜像层里则是 .wh.名字 条目,而不是字符设备。
在 Docker Desktop(macOS)上实测 volume 与 bind mount:docker rm 不删命名卷也不删匿名卷(要 rm -v);空卷第一次挂载会复制镜像该目录的内容而 bind mount 会盖住它;建 1000 个小文件命名卷 20 ms、可写层 42 ms、宿主机 bind mount 361 ms;-v 会自动创建不存在的宿主机目录而 --mount 报错。
在 Docker Desktop(macOS)上实测挂载卷的权限:bind mount 里容器 root 创建的文件在宿主机上是宿主机用户(uid 501)的,uid 1000 的容器用户可以写 755 的宿主机目录,容器里 chown 不改变宿主机属主;命名卷存真实 uid,镜像目录属主是 root 时 uid 1000 写入 Permission denied,属主是 1000 时空卷会继承并写入成功。
在 Docker Engine 29.8.2 里实测 tmpfs 挂载:默认大小是内存的一半(3967 MiB,MemTotal 7934 MiB),size=10m 写满报 No space left on device;容器重启后数据消失;写 100 MiB 内存增加 100.4 MiB;--memory 64m 时往 200m 的 tmpfs 写 150 MiB,dd 被 OOM 杀死(137)。