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

简介: 本文详解 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

点击查看答案

正确答案:B. docker push

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

- docker run:用于创建并启动容器,不是上传镜像。
- docker tag:只修改镜像引用名称,不负责网络上传。
- docker compose up -d:用于根据 Compose 配置创建或更新服务,不负责推送镜像到 ACR。

相关文章
|
20天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
8883 26
|
19天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
3821 16
|
18天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
2244 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
5天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型深度拆解:原理解读、实战测评与保姆级落地教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为**System One Model(系统一模型)**,对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
409 1
|
13天前
|
人工智能 Linux 开发者
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
Codex是OpenAI推出的AI编程智能体,可读取本地项目、理解需求并自动修改代码。支持桌面GUI、命令行(CLI)及VS Code/Cursor插件三种形态,覆盖可视化操作、终端高效开发与编辑器无缝集成场景,助开发者用自然语言驱动编码全流程。(239字)
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
|
6天前
|
存储 人工智能 并行计算
大模型本地部署终端选型方法论:以 Qwen3.8-27B 为例的四档分层完整流程
本文提出一套大模型本地部署终端选型方法论:定约束、定档位、定框架、定参数四步决策法,配合入门、主力、质量、无损四档分层模型。以 Qwen3.8-27B 实测数据为例,逐环节解读显存、带宽、存储、散热、系统、预算等要素,给出面向不同预算的优选方案、决策自查清单与市场观察框架。文末前瞻 AI 笔记本的 CPU+GPU 与统一内存两条路线,论证四步决策法在新品类上的延续性。
|
7天前
|
人工智能 Linux Windows
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
千问办公(QwenWork)是阿里云推出的AI智能办公平台,支持网页端直接使用及Windows/Mac/Linux客户端下载。提供PPT生成、财报分析、网页搭建等AI功能,个人版免费,企业版198元/席/月。详情见官网qwenwork.cn或阿里云产品页。
951 0
千问办公(QwenWork)官网入口:其实有2个,一个是网页端千问办公,一个是介绍指南页面
|
19天前
|
云安全 人工智能 安全