在自己的机器上起一个镜像仓库很容易,但删镜像为什么不释放磁盘?这篇用 registry:2 实测:共享层只存一份、DELETE 之后磁盘不变、garbage-collect 才真正回收,以及跨仓库推送时层是怎么被复用的。
DELETE /v2/c16/app/manifests/<digest> → 405;正文:{"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}registry:2 默认拒绝删除:DELETE manifest 返回 405 UNSUPPORTED。需要在启动时设置环境变量 REGISTRY_STORAGE_DELETE_ENABLED=true。
推 app:1 后:registry 磁盘上 blob 文件 4 个,共 6216 KB 再推 app:2 后:blob 文件 7 个,共 8352 KB(新增 3 个文件、2136 KB;输出里 "Layer already exists" 1 行)
两个镜像共用 alpine 基础层,各自有一个 2 MiB 的随机文件。推完两个镜像,磁盘上只有 7 个 blob 文件(8352 KB),第二次推送输出里有一行 Layer already exists。
DELETE manifests/<app:1 的 digest> → 202
tags/list → {"name":"c16/app","tags":["2"]}
GET manifests/1 → 404
删除后磁盘上 blob 文件 7 个,共 8320 KB(删除前 7 个、8352 KB)删除 app:1 的 manifest 后,tag 消失、GET 返回 404,但磁盘占用从 8352 KB 只降到 8320 KB。层的数据文件都还在。
--dry-run:退出码 0;输出里 "eligible for deletion" 的行数 4 dry-run 之后磁盘:7 个 blob 文件、8320 KB 真正执行:退出码 0;输出里 "eligible for deletion" 的行数 4 GC 之后磁盘:4 个 blob 文件、6248 KB(回收了 3 个文件、2072 KB)
在 registry 容器里执行 registry garbage-collect /etc/docker/registry/config.yml 才会回收没人引用的 blob:磁盘从 8320 KB 降到 6248 KB,7 个文件变 4 个。先用 --dry-run 看一遍不会改动。回收时有新的写入会怎样,我没有测。
docker pull app:2 → 退出码 0;localhost:9701/c16/app:2 docker pull app:1(已删除)→ 退出码 1;Error response from daemon: failed to resolve reference "localhost:9701/c16/app:1": localhost:9701/c16/app:1: not found
回收之后,没被删除的 app:2 可以重新拉取;已删除的 app:1 报 not found。
push 退出码 0;输出里 "Mounted from" 的行数 2,"Layer already exists" 的行数 0 f0deb84d7ced: Mounted from c16/app | 3f26bc2dec0b: Mounted from c16/app 之后磁盘:4 个 blob 文件、6336 KB(推之前 4 个、6248 KB)
同一个 registry 里,把 c16/app:2 推成 c16/other:2,docker 输出 Mounted from c16/app,没有重新上传层内容。磁盘上的 blob 文件数不变,总大小多了 88 KB(我没有查那是什么,推测是新仓库的元数据)。