使用 github action 来自动发布项目到 dockerhub。参考 https://msdemt.github.io/p/github-action-build-docker/ 博客

1. 准备工作

1.1 dockerhub token

https://hub.docker.com/settings/security

登录 dockerhub,在用户的 account settings 里面获取用户 token

image.png

将其添加到 github 仓库的 secrets 里面,具体位置是仓库设置中的 Secrets and variables 里面的 Actions 栏目中,如下图所示,添加 Repository secrets。

image.png

需要添加的是 DOCKER_USERNAME 为你的 docker 用户名(注意是用户名,不是邮箱),还有 DOCKER_TOKEN 为刚刚我们在 dockerhub 中获取的 token。

1.2 获取 github 操作 token

https://github.com/settings/tokens

到 GitHub 的用户设置中,创建一个 token,需要给予 repo、workflow、packages 权限。如果你不知道给予什么权限,直接全给他选上,保障这个 token 不泄露给外部就可以了。

image.png

另外,expiration 是过期日期,如果你担心泄漏造成问题,可以设置一个过期时间,但是需要到时间后去更新仓库的 secrets。

image.png

点击确定以后会得到 token,复制他,同样是到 github 仓库的 secrets 里面添加一个 RELEASE_TOKEN 变量。

2. 上传 workflows 文件

2.1 添加如下 yml 文件

前期的准备工作已经搞定了,现在就是添加一个 github action 的 yml 文件了。

在你的仓库里面创建一个.github/workflows 文件夹,并在里面创建一个.yml 文件,写入如下内容。

yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
name: docker images cicd
## 触发器设置
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

## 项目任务,任务之间可以并行调度
jobs:
build:
# 选择云端运行的环境
runs-on: ubuntu-latest
steps:
# uses代表使用一个模块,此处使用的是checkout模块,将github项目文件导入到当前环境中
- uses: actions/checkout@v3
# 使用with跟在后面来为前面的模块输入参数
with:
submodules: 'true'
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
# 这里用到了github的secrets功能,避免账户和密码随仓库泄露
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
# 设置当前的发行版本tag
- name: Release version
id: release_version
run: |
app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp")
echo "app_version=$app_version" >> $GITHUB_ENV
# 开始构建镜像
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: dockerfile
build-args: |
GITHUB_TOKEN=${{ secrets.RELEASE_TOKEN }}
platforms: |
linux/amd64
linux/arm64
linux/arm
push: true
# 指定用户/仓库名
tags: |
${{ secrets.DOCKER_USERNAME }}/kook-ticket-bot:latest
${{ secrets.DOCKER_USERNAME }}/kook-ticket-bot:${{ env.app_version }}
# 这里是通过md文件自动生成dockerhub描述的模块,也可以不需要
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: ${{ secrets.DOCKER_USERNAME }}/kook-ticket-bot
readme-filepath: ./README.md

对这里面的内容做一定说明,其中 secrets. 使用的就是我们刚刚添加到 github 仓库中的变量,分别用于访问 github 仓库和登录 dockerhub。

你会发现最末尾通过 readme 文件自动生成 dockerhub 的描述部分,多出来了一个上文没有提到的 secrets.DOCKER_PASSWORD,这个是你 dockerhub 账户的密码。如果你不需要自动生成 dockerhub 的描述,那就可以把最后一个 Docker Hub Description 条目直接删除了,否则需要添加这个 secrets。

项目中我使用了 version.py 文件来存放最新的版本号,该文件需要在项目的根路径中创建,内容格式如下

py
1
APP_VERSION = '版本号'

使用这个 workflows 文件,你只需要修改 ${{ secrets.DOCKER_USERNAME }}/kook-ticket-bot 里面右侧的镜像名字为你的项目名字,将 file: dockerfile 这里的 dockerfile 设置为你项目中 dockerfile 的文件路径就可以了。

另外,在这个 yml 中,指定了三个平台的 docker 镜像,这里可以根据你自己的实际需要来减少一些平台。毕竟大部分用户用的都是 amd64(即 x86)的电脑,如果没有用户需要使用 arm 平台,可以把后两项删除,以加快 github action 的运行速度。

yaml
1
2
3
4
platforms: |
linux/amd64
linux/arm64
linux/arm

最终完成 action 的截图如下

image.png

image.png

2.2 关于 GITHUB_REPOSITORY_NAME_PART 环境变量

在别的 github action 教学文章中,会提到使用 ${{ env.GITHUB_REPOSITORY_NAME_PART }} 来直接用 github 的仓库名字作为镜像名。但经过我的测试,这个方法不适用于本文的这个 workflows 文件,使用该环境变量会导致容器的名字多出来一个尾随的 /,最终的镜像名字变成了用户名/镜像名/:tag,不符合 dockerhub 中镜像的命名规范。以下是具体的 actions 执行错误截图。

image.png

The end

不过,根据 github actions 上的 warning,我这个 workflows 文件已经是老版本的了,里面使用的很多特性都即将不再支持,所以只是个临时用用的权宜之计,后续得去找个另外的 yaml 文件来处理这个 docker 镜像了。

2025.01.30 更新:新年快乐,今天实测本文的 workflow 文件依旧可用!