本节摘要:承接 2.3 的入门四动作,本节把镜像管理升级成体系:标签策略与内容摘要的可靠性差异、远程堆场与本地库存的对账方法、多堆场间的推拉规则。学完你能在任何网络环境下管好自己的货。
上一章你提过几票货,本节开始你还要自己造货、存货、发货。货一多,三个问题自然浮出来:引用怎么写才可靠?本地库存与堆场怎么对账?货在多个堆场之间怎么流转?本节沿着这三问展开。
2.3 节说过 latest 只是普通标签,本节把"标签可靠性"讲成可操作的规则。标签本质是可移动的指针:维护者随时可以把 1.25 重新指向新的构建,同一标签今天和明天提到的货可能不同。内容摘要(digest)则是货物的化学指纹:由每层内容的哈希逐层计算而来,内容变则摘要变。
实操上用一条命令体会两者的差别:
# 给本地镜像补打一个自定义标签(纯本地操作,不动堆场) docker tag nginx:1.25-alpine my-registry.example.com/base/nginx:stable # 查看两个引用指向同一批货(IMAGE ID 相同) docker images | grep nginx # my-registry.example.com/base/nginx stable 0c7ba8a3f7e2 # nginx 1.25-alpine 0c7ba8a3f7e2
一条镜像可以有任意多个标签,但 IMAGE ID 只有一个。据此得出团队协作的三条引用纪律:开发阶段用版本标签(可读性好,出问题好沟通);流水线与生产用摘要引用(镜像名@摘要,杜绝"标签漂移"引发的部署不一致);回滚时用旧版本的摘要(哪怕堆场上的标签已被人挪走,摘要引用照样原样提回)。
摘要引用长这样,日常 review 配置时能一眼认出来:
# 摘要引用格式:镜像名@sha256:摘要值 docker pull nginx@sha256:0423b3e07c628fd54ba6a5b1e79d0f2e2f3d4c9a2b3c1d0e9f8a7b6c5d4e3f2a # 输出示例: # nginx@sha256:0423...: Pulling from library/nginx # Digest: sha256:0423b3e07c628fd54ba6a5b1e79d0f2e2f3d4c9a2b3c1d0e9f8a7b6c5d4e3f2a # Status: Downloaded newer image for nginx@sha256:0423...
库存多起来之后,images 清单会越来越长,三个对账命令配合使用:
# 列出本地全部库存(--digests 一列把摘要带出来,便于核对) docker images --digests # REPOSITORY TAG DIGEST IMAGE ID SIZE # nginx 1.25-alpine sha256:0423b3e07c62... 0c7ba8a3f7e2 71.8MB # redis 7-alpine sha256:926fac19233c... a1b2c3d4e5f6 41.7MB # 查哪些镜像正被容器占用(悬空引用排查) docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" # NAMES IMAGE STATUS # web01 nginx:1.25-alpine Up 3 hours
清理是管理的重要半边。垃圾货主要有两类:悬空镜像(dangling,旧标签被新构建顶替后留下的无名层)和长期无人使用的镜像。批量清理有现成的动作:
# 只清理悬空镜像(安全,不碰正常库存) docker image prune # 输出示例:Total reclaimed space: 213MB # 清理所有"当前没有被容器使用"的镜像(谨慎:会删掉库存里闲置的货) docker image prune -a # 确认提示后执行,输出会汇总释放的磁盘
生产机器上建议把 image prune 挂进定期维护任务——磁盘被悬空层悄悄吃满导致部署失败,是老运维都见过的经典事故。
造好的货要发到堆场,动作是对 pull 的镜像:push。完整走一遍"标地址、推送、验证"的闭环(堆场地址以内网自建堆场为例,搭建方法在 3.5 节):
# 第一步:给镜像打上"目的堆场地址"前缀的完整名称 docker tag myapp:1.0.0 registry.example.com/team-a/myapp:1.0.0 # 第二步:推送到目标堆场(只有本地已有、堆场没有的层会真正上传) docker push registry.example.com/team-a/myapp:1.0.0 # 输出示例: # The push refers to repository [registry.example.com/team-a/myapp] # 8e5f2a1c3d7b: Pushed <- 新层上传 # 71a4b0d9c2e8: Layer already exists <- 共享层秒过(分层的传输红利) # 1.0.0: digest: sha256:7d1f... size: 1571 # 第三步:换一台机器按摘要验证拉取,闭环完成 docker pull registry.example.com/team-a/myapp@sha256:7d1f...
注意 push 输出里的 "Layer already exists"——3.1 节讲的分层传输红利在这里兑现:同一团队推送的多个镜像共享基础层,堆场与带宽的开销都按"增量"计费。远近场分工也由此清晰:公共堆场放通用底货(操作系统、语言运行时、开源软件),私有堆场放业务货(自家应用镜像),前者省心后者安全。补一句实操提醒:第一次向某个私有堆场推送前,客户端要先完成登录(docker login 加堆场地址),否则推送会被拒绝——凭证管理在 3.5 节搭堆场时一并实操。
管货的规矩立好了。下一节进核心手艺站:亲手写装箱单。