前一阵子,我想在 Mathcheap 上实现 LaTeX 导出到 DOCX 格式的功能,一直没有找到合适的 JS 库去实现。目前可以很好实现这个功能的是 Pandoc , 美中不足的是 Pandoc 是 haskell 语言开发的,无法在 Node 环境和边缘服务器中运行。为了克服这个限制,我将 Pandoc 编译为 Webassembly。上周,我开源了 pandoc-wasm
这个编译流程,通过 Docker 镜像发布在 Docker Hub 上。在这个过程中,我探索了如何利用 GitHub Actions 自动构建和发布 Docker 镜像,极大地提升了开源项目的集成和部署效率。
为什么需要自动发布 Docker 镜像?
在尝试将 Pandoc 运行环境迁移到 Node 服务器的过程中,我试着构建了一套可靠的 pandoc-wasm
编译流程。因为 Mathcheap 依赖这套编译流程打包的产物,我打算开源并长期升级维护。Docker 是实现这一目标的绝佳工具,它可以将应用及其所有依赖打包到一个标准化的容器中。但每次手动构建镜像、打标签、然后推送到 Docker Hub 的过程,不仅繁琐,而且容易出错。尤其是在一个频繁迭代的开源项目中,自动化这一流程显得至关重要。这不仅能节省时间,还能确保每次代码合并后都能生成一个可靠的镜像。GitHub Actions 正是实现这一目标的利器。
准备工作
在开始之前,请确保你已经准备好以下几样东西:
- GitHub 仓库
- Docker Hub 账号
- Dockerfile 文件
Dockerfile
是一个文本文档,包含了一系列用户可以调用来组装镜像的指令。
第一步:配置 Docker Hub 访问凭证
为了让 GitHub Actions 能够登录你的 Docker Hub 账号并推送镜像,你需要将用户名和访问令牌(Access Token)安全地存储在 GitHub 中。
-
生成 Docker Hub 访问令牌:
- 登录 Docker Hub。
- 进入 "Settings" -> "Personal access tokens"。
- 点击 "Generate new token",创建一个具有读写删权限的令牌,并立即复制它。
-
在 GitHub 仓库中设置 Secrets:
- 进入你的 GitHub 仓库,点击 "Settings" -> "Secrets and variables" -> "Actions"。
- 点击 "New repository secret",创建两个新的 Secret:
DOCKERHUB_USERNAME
: 你的 Docker Hub 用户名。DOCKERHUB_TOKEN
: 你刚刚生成的访问令牌。
通过这种方式,我们可以在工作流程中安全地使用这些凭证,而无需将它们硬编码到代码中。
第二步:创建 GitHub Actions 工作流程
接下来,在项目中创建一个 YAML 文件来定义自动化工作流程。
- 在仓库根目录下,创建
.github/workflows/
文件夹。 - 在该文件夹下,创建一个新的 YAML 文件,例如
docker-publish.yml
。
yaml
name: Build and Publish Docker image
on:
push:
tags:
- "v*"
workflow_dispatch:
env:
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: ./docker
file: ./docker/Dockerfile
push: true
tags: |
${{ env.IMAGE_NAME }}:${{ github.ref_name }}
${{ env.IMAGE_NAME }}:latest
- name: Update Docker Hub description
uses: peter-evans/dockerhub-description@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: ${{ env.IMAGE_NAME }}
short-description: ${{ github.event.repository.description }}
readme-filepath: ./docker/README.md
解读工作流程文件
分解一下这个 YAML 文件的关键部分:
- 触发条件
on
:push.tags
: 以 v 开头的标签(例如 v1.0.0)。这能把镜像版本与项目版本对齐。- workflow_dispatch: 支持从 GitHub UI 手动触发。
env.IMAGE_NAME
: 最终镜像名是shenlu89/pandoc-wasm
,shenlu89
是我在 Docker Hub 的用户名,DOCKERHUB_USERNAME
,仓库名来自当前 GitHub 仓库的名字。docker/build-push-action@v5
:context
: 指向./docker
目录与其中的 Dockerfile。push
:true
表示构建完成后会推送到远程。tags
: 同时推版本标签和latest
。
peter-evans/dockerhub-description@v4
:- 用仓库的简介和
./docker/README.md
自动更新 Docker Hub 页面描述。
- 用仓库的简介和
提交代码触发 GitHub Actions
推送标签触发发布
- 创建并推送一个符合规则的版本标签,例如 v1.0.0:
bash
git add . && git commit -m 'feat: xxx'
git tag v1.0.0
git push origin v1.0.0
- 或者在 GitHub 的 Actions 页面手动点击"Run workflow"。
最后,触发 GitHub Actions 工作流,自动完成镜像构建和推送 Docker Hub。
- Mathcheap: mathcheap.xyz
- pandoc-wasm: github.com/shenlu89/pa...
- pandoc-wasm (Docker Hub): hub.docker.com/r/shenlu89/...