构建制品

GitBeginner
立即练习

简介

在上一个实验中,你学习了「质量控制」(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):

  1. docker/login-action:登录镜像仓库。
  2. 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

验证制品

机器人现在正在忙碌:它会设置服务器、登录、构建容器,然后上传容器。

  1. 进入 GitHub 上的仓库页面。
  2. 点击 Actions 标签页。
  3. 点击名为「Docker Publish」的工作流运行记录。
  4. 等待各个步骤变为绿色。

Docker Publish

当「Build and push Docker image」步骤成功完成后,你的软件包就已经存放在仓库中。现在查看它。

  1. 进入仓库主页的 Code 标签页。
  2. 查看右侧边栏。你应该能看到名为 Packages 的区域。
  3. 其中会列出一个新的软件包!

点击软件包名称查看详细信息。这就是已经完成的制品。现在,任何有权访问你仓库的用户(如果仓库是公开的,则包括所有公众用户)都可以使用此镜像下载并运行你的应用。

GitHub Packages

总结

在本实验中,你构建了一个完整的交付流水线。

你学习了:

  • 打包:如何编写 Dockerfile,将应用放入容器。
  • 权限:如何授予工作流写入软件包的权限。
  • 仓储:如何使用 GitHub Container Registry(GHCR)存储镜像。
  • 自动化:如何使用标准 actions 自动构建并交付代码。

现在,你的机器人助手已经能够检查代码(CI)并交付代码(制品)。在下一个实验中,我们将学习如何安全地处理密码等敏感信息。