Docker 教程

Docker 镜像发布

1. 深入理解 Docker 镜像标签 (Tags)

Docker 镜像标签(Tags)就像是给镜像贴上的“易读便利贴”,主要用来标识镜像的特定版本或变体。一个完整的标签名称由两部分组成:仓库名标签名,中间用冒号 (:) 隔开。如果你在操作时不指定标签,Docker 永远会默认使用 latest 这个标签。

1.1 Docker 标签的解剖学

一个完全符合规范的 Docker 镜像名称长这样:docker.io/username/image_name:tag。让我们把它拆开来看看:

  • docker.io: 这是镜像仓库(Registry)的域名。如果你不写,Docker 默认你是在使用官方的 Docker Hub (docker.io)。如果你使用的是其他公司的仓库,就要换成他们的域名(比如 Google 的 gcr.io,或者你公司内部的仓库域名)。
  • username: 你的 Docker Hub 用户名(或组织名)。这非常重要,它告诉 Docker Hub 你的镜像应该存放在哪个“文件夹”下。
  • image_name: 你给这个镜像起的具体名字。名字应该简单明了,能体现这个镜像里装的是什么应用或服务。
  • tag: 具体的版本号或变体标识。常见的标签有 latest(最新版)、1.02.0-beta(测试版)、stable(稳定版),甚至可以使用代码提交的哈希值(Commit Hash)。

1.2 为什么要费心打标签?

  • 版本控制 (Versioning):标签让你能够同时维护应用的不同版本(如 1.01.1latest 并存)。
  • 可重复性 (Reproducibility):在生产环境中,你绝不应该使用随时可能变化的 latest 标签,而应该使用明确的数字版本号标签。这能确保每次部署拉取的都是完全一样的内容。
  • 组织管理 (Organization):通过标签可以轻松区分应用的当前状态,比如用标签区分开发环境 (dev)、测试环境 (staging) 和生产环境 (prod) 的镜像。
  • 快速回滚 (Rollbacks):如果刚上线的 2.0 版本出了致命 Bug,你只需要把服务器上的镜像标签改回 1.9,就能瞬间完成回滚。

2. 给现有的镜像打标签

我们使用 docker tag 命令来给镜像贴标签。它的基本语法是:

docker tag 源镜像[:旧标签] 目标镜像[:新标签]
  • 源镜像:你想打标签的那个镜像。可以用镜像 ID,也可以用它现有的名字和标签。
  • 目标镜像:你要赋予它的新名字和新标签。格式必须是 用户名/镜像名:标签

2.1 打标签实战演示

场景一:通过镜像 ID 打标签
假设你用 docker images 看到一个刚刚构建好的镜像,它的 ID 是 a1b2c3d4e5f6,你想把它命名为版本 1.0

docker tag a1b2c3d4e5f6 myusername/myimage:1.0

场景二:给已有的镜像加个新标签
假设你本地已经有一个叫 myimage:latest 的镜像,你想给它加个 1.0 的标签,同时加上你的用户名以备推送。

docker tag myimage:latest myusername/myimage:1.0

注意:这不会复制镜像本身,它只是给同一个物理镜像多贴了一张便利贴。这两个标签现在指向的是完全相同的底层镜像层。

场景三:发布 Beta 测试版
你对 webapp 做了一次大重构,想发个测试版。

docker tag webapp:latest myusername/webapp:2.0-beta

这样,测试人员就可以专门去拉取 2.0-beta 进行测试,而普通用户依然安全地使用着 latest 版本。

3. 把镜像推送到 Docker Hub

标签打好了,接下来就是激动人心的发布环节!在推送之前,你必须先在终端里登录你的 Docker Hub 账号。

3.1 登录 Docker Hub

使用 docker login 命令:

docker login

终端会提示你输入 Docker Hub 的用户名和密码。如果你开启了双因素认证 (2FA),这里不能输登录密码,必须去网页端生成一个个人访问令牌 (Personal Access Token) 当作密码输入。

3.2 执行推送操作

使用 docker push 命令将打好标签的镜像推送到云端。语法很简单:

docker push 镜像名称[:标签]

示例:
把刚才打好标签的 1.0 版本推上去:

docker push myusername/myimage:1.0

你会看到终端开始显示进度条,Docker 正在把镜像一层一层地上传到 Docker Hub。

推送多个标签:
如果你想让这个 1.0 版本同时也作为最新的默认版本,你需要把两个标签都推上去:

docker push myusername/myimage:1.0
docker push myusername/myimage:latest

3.3 常见推送失败排查 (Troubleshooting)

  • "denied: requested access to the resource is denied":最常见的错误。通常是因为你忘记登录了,或者你试图推送到的那个 username 根本不是你自己的账号。检查一下镜像名字里的用户名是不是拼写错了。
  • "unauthorized: authentication required":身份验证过期或失败。重新执行一次 docker login 即可。
  • "403 Forbidden":通常发生在你试图推送到一个企业/组织账号下的仓库,但你的个人账号没有被管理员授予“写入 (Write/Push)”权限。

4. 镜像层 (Layers) 与推送优化机制

Docker 镜像是分层的。当你在执行 docker push 时,Docker 非常聪明,它只会上传 Docker Hub 上目前还没有的那些层

如果你只是改了应用代码里的一行字重新构建,大部分底层的系统层和依赖包层在 Docker Hub 上早就存在了,Docker 会直接跳过它们,只上传那几十 KB 发生变动的代码层。这就是为什么第一次推送可能需要几分钟,而之后的更新推送往往只需几秒钟。

4.1 如何让推送和拉取更快?

镜像越小,网络传输就越快。我们在上一章详细讲过优化技巧,这里简单复习一下:

  1. 使用轻量级基础镜像:比如选用 Alpine Linux。
  2. 合并命令:&& 把多个 RUN 指令串起来,减少层数。
  3. 勤清理:装完软件立刻删掉安装包缓存。
  4. 多阶段构建 (Multi-stage builds):终极杀手锏,把编译环境和运行环境分离,只保留最终的运行产物。