讲解

镜像是如何跨越机器流动的?靠仓库(registry)。Docker Hub 是默认公共仓库;企业里常用私有仓库(Harbor、云厂商的 ACR/ECR)存放业务镜像——地址写在镜像名第一段,比如 registry.cn-hangzhou.aliyuncs.com/team/app:1.0。推拉流程:docker login 认证(凭证存 ~/.docker/config.json)→ docker build -t 完整名字:标签 构建时直接打成目标名字(或 docker tag 现有镜像 改名)→ docker push 推送 → 另一台机器 docker pull 拉回。推送按层增量进行,共享的基础层不会重复上传。

标签策略是发布工程的基石。反面教材:只用 latest——回滚时说不清线上跑的是哪一版。稳妥做法:每次发布打「语义版本 + git 短哈希」双标签(app:1.4.2 + app:a1b2c3d),latest 只作为「最近稳定」的便利指针;不可变发布用 digest(镜像内容的 sha256,app@sha256:...)锁定,任何标签被覆盖都不影响 digest 的指向。

离线场景有第三条路:docker save 把镜像导出成 tar 归档(含所有层与标签),U 盘拷到内网机器 docker load 导入——涉密或隔离网络的标准搬运方式。配合 docker image inspect 的 digest 核对,可以保证「拷过去的和发出来的是同一份」。

示例

给已有镜像打一个「私有仓库风格」的完整名字(tag 只是改名,不复制数据):

docker tag ohmydocs-verify-web:1.0 registry.example.com/tutorial/web:1.0.0
docker images registry.example.com/tutorial/web

save 导出为 tar,模拟离线分发(导出后可以 docker load 到任何机器):

docker save ohmydocs-verify-web:1.0 -o web-image.tar && ls -lh web-image.tar | awk '{print $5, $9}'

删掉本地镜像再从 tar 恢复,验证 load 的还原能力:

docker rmi ohmydocs-verify-web:1.0 >/dev/null
docker load -i web-image.tar
docker images ohmydocs-verify-web

推送命令长这样(没有真实仓库,此处仅示意):

# 仅示意:推送需要先 docker login,且仓库真实存在
docker login registry.example.com && docker push registry.example.com/tutorial/web:1.0.0

清理演示用的别名镜像:

docker rmi registry.example.com/tutorial/web:1.0.0 >/dev/null && echo "别名已删"

常见坑

  • push 前忘 login 或没权限:denied: requested access to the resource is denied——先 login,且镜像名的命名空间要是你有权限的那个。
  • 镜像名不带仓库地址:docker push myapp:1.0 默认往 Docker Hub 的 library 推,必然失败;私有仓库地址是镜像名的一部分。
  • latest 覆盖发布:回滚无路、审计无据;版本标签 + digest 双保险。
  • save 忘带标签参数:docker save 镜像ID 导出的 tar 不含标签,load 后是 ——按「名字:标签」导出。

小结

仓库地址是镜像名的一部分;tag 改名、push/pull 增量按层传输、save/load 走离线;标签策略用语义版本 + git 哈希,锁死用 digest。下一章转向运维视角:日志与排障。