GitHub Actions 工作流 CI/CD 的“发布”

举报
小陈运维 发表于 2026/10/11 17:05:06 2026/10/11
【摘要】 本文详解 GitHub Actions 中 `file-server-docker` 项目的 CI/CD 发布流程:涵盖镜像打标(Tag)、ACR 登录、`docker tag` 重命名、`docker push` 推送及版本回滚五步核心实践,强调标签规范、安全凭证管理与可追溯部署。

GitHub Actions 工作流 CI/CD 的“发布”

围绕你的 file-server-docker 项目,把五件事串起来:

  1. 镜像标签(Tag)
  2. Registry 登录
  3. docker tag
  4. docker push
  5. 版本回滚

第一步:理解发布的完整流程

先看整体链路:

flowchart TD
    A["GitHub 代码仓库\n源代码 + Dockerfile"]
    --> B["docker build\n构建本地 Docker 镜像"]
    --> C["docker tag\n为同一个镜像增加仓库地址和版本标签"]
    --> D["Registry 登录\n获得向目标镜像仓库推送的权限"]
    --> E["docker push\n将镜像上传到阿里云 ACR"]
    --> F["部署服务器\n拉取指定版本,启动容器,验证健康状态"]

注意:docker tag 不负责上传镜像,docker push 才负责上传;Registry 登录也不会自动帮你构建镜像。


第二步:镜像标签究竟是什么?

假设你构建了一个镜像:

docker build -t file-server:latest .

这里的:

file-server:latest

是镜像名称和标签。

可以把镜像理解成一个应用的完整打包结果,而标签相当于给这个打包结果贴上的名字。

常见的标签有三类:

标签 示例 用途
浮动标签 latest 通常表示当前主推版本,但含义由发布流程约定
版本标签 v1.2.0 便于人工识别正式版本
提交标签 sha-a1b2c3d 将镜像与某次 Git 提交关联

为什么不建议只使用 latest?

假设你今天发布了:

file-server:latest → 版本 A

明天又发布了:

file-server:latest → 版本 B

同一个标签现在指向版本 B。

如果服务器之前运行版本 A,而你只记录了 latest,之后想回滚时,就很难仅凭这个标签确定之前到底运行的是哪个版本。

更好的方式是同时发布:

file-server:latest
file-server:sha-a1b2c3d

下一次发布时:

file-server:latest
file-server:sha-e4f5g6h

这样,latest 可以指向当前发布版本,而旧的提交标签仍然可以用于定位历史版本,前提是仓库没有删除或覆盖这些标签。

建议:生产部署使用明确的版本标签或镜像 digest,latest 只作为辅助标签。

第三步:Registry 登录到底做了什么?

Registry 就是 Docker 镜像仓库。你可以把它理解成存放镜像的远程服务器。

你当前项目使用的目标仓库命名空间是:

registry.cn-hangzhou.aliyuncs.com/chenby

假设镜像仓库名为 file-server,完整镜像地址就可以写成:

registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d

它由四部分组成:

字段 值
Registry 地址 registry.cn-hangzhou.aliyuncs.com
命名空间 / 用户或组织空间 chenby
镜像仓库名 file-server
镜像标签 sha-a1b2c3d

1. 登录命令

一般形式:

docker login registry.cn-hangzhou.aliyuncs.com

执行后,Docker 会要求输入用户名和密码或访问凭证。对于阿里云 ACR,具体凭证应使用该实例或仓库对应的登录凭证。

登录的作用是让 Docker 获得相应仓库的访问权限。它不会构建镜像,也不会上传镜像。

2. GitHub Actions 中怎样登录?

不要把仓库密码直接写进 YAML 文件,更不要提交到 GitHub 仓库。

在 GitHub 仓库的 Settings → Secrets and variables → Actions 中配置必要的 Secrets,例如:

  • ACR_USERNAME
  • ACR_PASSWORD

然后在 Workflow 中使用登录 Action:

- name: Login to ACR
  uses: docker/login-action@v3
  with:
    registry: registry.cn-hangzhou.aliyuncs.com
    username: ${{ secrets.ACR_USERNAME }}
    password: ${{ secrets.ACR_PASSWORD }}

这里有两个重要区别:

  • registry 是仓库服务的地址,不是完整的镜像地址。
  • secrets.ACR_PASSWORD 是从 GitHub Secrets 读取凭证,不是 YAML 中的明文密码。

实际使用时,应为自动化任务创建权限尽可能小的专用凭证,并根据阿里云 ACR 的权限模型限制其访问范围。


第四步:docker tag 到底干了什么?

假设你先构建了本地镜像:

docker build -t file-server:latest .

查看本地镜像:

docker images

你可能看到:

REPOSITORY     TAG       IMAGE ID
file-server    latest    a1b2c3d4e5f6

现在要把它发布到 ACR,需要为它增加一个完整的仓库地址。

执行:

docker tag file-server:latest \
  registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d

此时,你再执行:

docker images

可能看到:

REPOSITORY                                               TAG           IMAGE ID
file-server                                              latest        a1b2c3d4e5f6
registry.cn-hangzhou.aliyuncs.com/chenby/file-server     sha-a1b2c3d    a1b2c3d4e5f6

注意两行的 IMAGE ID 相同。

这意味着 docker tag 通常只是给同一个本地镜像增加另一个名称,而不是重新构建一份镜像,也不是把镜像上传到网络。

可以把它想成给同一个文件增加一个新的引用名称:内容没变,只是增加了一个指向它的名字。

这里最容易出错的地方

docker tag 的格式是:

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
  • SOURCE_IMAGE:本地已经存在的镜像。
  • TARGET_IMAGE:准备使用的新名称。
  • TAG:可选的标签;如果省略,通常默认使用 latest。

如果源镜像不存在,就会报错。docker tag 不会替你从 Dockerfile 构建镜像。


第五步:docker push 才是真正上传

前面已经完成:

  1. 构建镜像。
  2. 登录 ACR。
  3. 为镜像添加完整地址和版本标签。

现在执行:

docker push \
  registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d

Docker 会将目标镜像所需的数据层上传到对应仓库,并发布该标签的引用。

流程是:

flowchart TD
    A["本地镜像\nfile-server:latest"]
    --> B["docker tag\n增加 ACR 地址和版本标签"]
    --> C["docker push\n上传到远程镜像仓库"]
    --> D["ACR 远程仓库\n其他有权限的机器可以拉取该版本"]

推送成功后,你可以在 ACR 控制台中查看镜像仓库和对应标签。

但是,推送成功只说明镜像已经发布到仓库,并不代表生产服务器已经运行这个版本。服务器还需要执行拉取和部署。

把这几个命令放在一起看

下面是一个从构建到推送的完整示例。请确保目标仓库 chenby/file-server 已经创建,并且你有相应权限。

# 1. 构建镜像
docker build -t file-server:latest .

# 2. 登录仓库
docker login registry.cn-hangzhou.aliyuncs.com

# 3. 添加版本标签
docker tag file-server:latest \
  registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d

# 4. 推送镜像
docker push \
  registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d

这四步各司其职:

命令 作用
docker build 构建本地镜像
docker login 认证仓库访问权限
docker tag 为镜像增加目标名称和标签
docker push 上传镜像到远程仓库

注意:上面的 sha-a1b2c3d 是示例标签。真实的 GitHub Actions 应当使用实际提交 SHA 或其他明确的版本标识,不能把示例字符串直接当作真实版本。


第六步:服务器怎样拉取并运行指定版本?

镜像推送到 ACR 后,服务器可以执行:

docker pull \
  registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d

然后通过 Docker Compose 指定该版本。

例如,Compose 文件可以使用环境变量:

services:
  file-server:
    image: ${FILE_SERVER_IMAGE}
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - ./uploads:/data/uploads

这里的端口、容器路径和服务名称都是示例,必须与你项目的实际配置一致。

部署时可以这样指定镜像:

export FILE_SERVER_IMAGE="registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d"

docker compose pull
docker compose up -d

docker compose pull 会拉取 Compose 配置中指定的镜像,docker compose up -d 会按配置创建或更新容器。

有个细节要注意:export 只在当前 Shell 会话及其子进程中生效。如果你在另一个终端或另一次 SSH 会话中执行命令,需要重新设置变量,或者使用专门的部署环境文件。


第七步:如何实现版本回滚?

假设你先后发布了两个版本:

flowchart TD
    A["旧版本:sha-a1b2c3d\n已验证可用,应该保留作为回滚目标。"]
    --> B["新版本:sha-e4f5g6h\n已经推送并尝试部署,但健康检查失败。"]
    --> C["恢复旧版本\n重新指定旧标签,拉取并更新服务,然后再次验证健康状态。"]

如果 Compose 使用前面的 FILE_SERVER_IMAGE 变量,回滚可以是:

export FILE_SERVER_IMAGE="registry.cn-hangzhou.aliyuncs.com/chenby/file-server:sha-a1b2c3d"

docker compose pull
docker compose up -d

这会将 Compose 配置指向旧版本。前提是旧镜像仍然存在于仓库中,且服务器可以访问它。

回滚并不等于删除新镜像。 新镜像可以留在仓库中供排查问题;真正重要的是让服务重新运行已知可用的版本。

还要特别注意:

  • 用户上传的文件应存放在持久化卷或可靠的外部存储中。
  • 如果新版本修改了数据库结构或文件格式,单纯回滚镜像可能不够。
  • docker compose up -d 返回成功后,还需要检查容器健康状态和业务接口。
  • 如果部署过程中旧容器已经被替换,恢复旧版本仍可能产生短暂中断。需要更高可用性时,要设计新旧实例并行运行、流量切换等策略。

第八步:把整个发布流程记成一句话

构建镜像 → 登录 Registry → 为镜像打版本标签 → 推送镜像 → 服务器拉取指定版本 → 部署并检查 → 失败则恢复旧版本。

你可以用下面的交互小测验检验一下自己是否真正理解了。

发布流程小测验

你已经执行了 docker build 和 docker tag,并且成功登录了 ACR。接下来要把镜像真正上传到仓库,应该执行哪个命令?

  • A. docker run
  • B. docker push
  • C. docker tag
  • D. docker compose up -d
<summary>点击查看答案</summary>

正确答案:B. docker push

docker push 会将本地镜像推送到远程 Registry。前面的 docker tag 只是为镜像增加目标名称,并不会上传。

  • docker run:用于创建并启动容器,不是上传镜像。
  • docker tag:只修改镜像引用名称,不负责网络上传。
  • docker compose up -d:用于根据 Compose 配置创建或更新服务,不负责推送镜像到 ACR。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。