简介
在上一个实验中,你学习了「质量控制」(CI)。现在,我们进入下一步:打包。
可以把软件想象成工厂生产的产品。产品通过所有质量测试后,还需要装箱、封装并贴上标签,才能发货给客户。在软件领域,这个「箱子」通常就是 Docker 容器。
我们把打包后的产物称为 制品(artifact)。制品构建完成后,需要存储在镜像仓库中,这样部署等后续阶段就能获取完全相同的构建结果。
这种可复现性是关键。部署时应该使用已知的构建产物,而不是在每台目标机器上以不同方式重新构建代码。
GitHub 提供了一个名为 GitHub Container Registry(GHCR)的镜像仓库。
在本实验中,你将教会机器人助手完成以下任务:
- 将应用打包为 Docker 容器。
- 使用版本标签为容器标记。
- 自动将容器发货(推送)到 GitHub 仓库。
前置条件
我们将继续使用 github-actions-basics 仓库。
创建 Dockerfile
机器人要打包应用,首先需要明确的操作说明。在 Docker 中,这些说明写在一个名为 Dockerfile 的特殊文件中。
进入项目目录。
cd ~/project
git clone https://github.com/your-username/github-actions-basics.git
cd github-actions-basics
注意:将 your-username 替换为你实际的 GitHub 用户名。
创建名为 Dockerfile 的文件(D 必须大写,且不带扩展名),内容如下:
cat > Dockerfile << EOF
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
EOF
下面逐项说明这份打包清单要求机器人执行的操作:
- **
FROM node:16-alpine**:使用一个已经安装 Node.js 的轻量级基础系统。 - **
WORKDIR /app**:在容器内部创建工作目录。 - **
COPY ...**:将项目文件复制到容器中。 - **
RUN npm install**:在容器内部安装所需依赖。 - **
CMD ...**:有人启动这个容器时,运行应用。
现在,将该文件添加到仓库,并推送到 GitHub。
git add Dockerfile
git commit -m "Add Dockerfile"
git push
创建发布工作流
现在创建一个新的工作流,用于处理打包和发货。我们将它命名为 docker-publish.yml。
创建该文件:
touch .github/workflows/docker-publish.yml
使用 nano 打开文件。
nano .github/workflows/docker-publish.yml
添加以下配置。这里将介绍一个名为 permissions 的新概念。
name: Docker Publish
on:
push:
branches: ["master", "main"]
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
为什么需要设置权限?
出于安全考虑,机器人默认只有有限的访问权限。由于我们希望机器人将内容上传到你的 GitHub 账户中的「packages」部分,因此必须明确授予它进入仓库的权限。packages: write 就是用于执行此操作的配置。
这是流水线设计中最小权限原则的一个很好示例。工作流只应获得完成自身任务所需的权限。
保存并退出 nano(Ctrl+X、Y、Enter)。
添加构建和推送步骤
现在验证最关键的部分:实际构建并推送镜像。
我们将使用 Docker 提供的两个官方工具(actions):
docker/login-action:登录镜像仓库。docker/build-push-action:构建容器并将其推送出去。
这一阶段连接了 CI 和交付流程。测试通过后,流水线会创建带版本信息的制品,其他系统之后可以直接部署该制品,而不必从源代码重新构建。
再次打开 .github/workflows/docker-publish.yml。
nano .github/workflows/docker-publish.yml
将以下步骤追加到 build-and-push 任务中:
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}/app:latest
理解这些神奇变量:
- **
ghcr.io**:这是 GitHub「仓库」的地址。 - **
${{ github.actor }}**:这是一个变量,会自动填入你的 GitHub 用户名。 - **
${{ secrets.GITHUB_TOKEN }}**:这是 GitHub 为机器人创建的特殊临时密码。你不需要进行任何操作,它会自动生效!该令牌允许机器人安全登录,无需你输入密码。 - **
tags**:这会为容器创建标签。其格式为:仓库地址 / 你的用户名 / 仓库名称 / 应用名称 : 版本。
保存并退出 nano。
现在,将此工作流推送到 GitHub,启动整个流程。
git add .
git commit -m "Add Docker publishing workflow"
git push
验证制品
机器人现在正在忙碌:它会设置服务器、登录、构建容器,然后上传容器。
- 进入 GitHub 上的仓库页面。
- 点击 Actions 标签页。
- 点击名为「Docker Publish」的工作流运行记录。
- 等待各个步骤变为绿色。

当「Build and push Docker image」步骤成功完成后,你的软件包就已经存放在仓库中。现在查看它。
- 进入仓库主页的 Code 标签页。
- 查看右侧边栏。你应该能看到名为 Packages 的区域。
- 其中会列出一个新的软件包!
点击软件包名称查看详细信息。这就是已经完成的制品。现在,任何有权访问你仓库的用户(如果仓库是公开的,则包括所有公众用户)都可以使用此镜像下载并运行你的应用。

总结
在本实验中,你构建了一个完整的交付流水线。
你学习了:
- 打包:如何编写
Dockerfile,将应用放入容器。 - 权限:如何授予工作流写入软件包的权限。
- 仓储:如何使用 GitHub Container Registry(GHCR)存储镜像。
- 自动化:如何使用标准 actions 自动构建并交付代码。
现在,你的机器人助手已经能够检查代码(CI)并交付代码(制品)。在下一个实验中,我们将学习如何安全地处理密码等敏感信息。



