跳转到内容

GitHub Actions

2 篇包含标签 "GitHub Actions" 的文章

HagiCode 实践:如何利用 GitHub Actions 实现 Docusaurus 自动部署

为 HagiCode 添加 GitHub Pages 自动部署支持

Section titled “为 HagiCode 添加 GitHub Pages 自动部署支持”

本项目早期代号为 PCode,现已正式更名为 HagiCode。本文记录了如何为项目引入自动化静态站点部署能力,让内容发布像喝水一样简单。

在 HagiCode 的开发过程中,我们遇到了一个很现实的问题:随着文档和提案越来越多,如何高效地管理和展示这些内容成了当务之急。我们决定引入 GitHub Pages 来托管我们的静态站点,但是手动构建和部署实在是太麻烦了——每次改动都要本地构建、打包,然后手动推送到 gh-pages 分支。这不仅效率低下,还容易出错。

为了解决这个问题(主要是为了偷懒),我们需要一套自动化的部署流程。本文将详细记录如何为 HagiCode 项目添加 GitHub Actions 自动部署支持,让我们只需专注于内容创作,剩下的交给自动化流程。

嘿,介绍一下我们正在做的东西

我们正在开发 HagiCode——一款 AI 驱动的代码智能助手,让开发体验变得更智能、更便捷、更有趣。

智能——AI 全程辅助,从想法到代码,让编码效率提升数倍。便捷——多线程并发操作,充分利用资源,开发流程顺畅无阻。有趣——游戏化机制和成就系统,让编码不再枯燥,充满成就感。

项目正在快速迭代中,如果你对技术写作、知识管理或者 AI 辅助开发感兴趣,欢迎来 GitHub 看看~

在动手之前,我们得先明确这次任务到底要干啥。毕竟(这里打错了,应该是毕竟)磨刀不误砍柴工嘛。

  1. 自动化构建:当代码推送到 main 分支时,自动触发构建流程。
  2. 自动部署:构建成功后,自动将生成的静态文件部署到 GitHub Pages。
  3. 环境一致性:确保 CI 环境和本地构建环境一致,避免”本地能跑,线上报错”的尴尬。

考虑到 HagiCode 是基于 Docusaurus 构建的(一种非常流行的 React 静态站点生成器),我们可以利用 GitHub Actions 来实现这一目标。

GitHub Actions 是 GitHub 提供的 CI/CD 服务。通过在代码仓库中定义 YAML 格式的工作流文件,我们可以定制各种自动化任务。

我们需要在项目根目录下的 .github/workflows 文件夹中创建一个新的配置文件,比如叫 deploy.yml。如果文件夹不存在,记得先手动创建一下。

这个配置文件的核心逻辑如下:

  1. 触发条件:监听 main 分支的 push 事件。
  2. 运行环境:最新版的 Ubuntu。
  3. 构建步骤
    • 检出代码
    • 安装 Node.js
    • 安装依赖 (npm install)
    • 构建静态文件 (npm run build)
  4. 部署步骤:使用官方提供的 action-gh-pages 将构建产物推送到 gh-pages 分支。

以下是我们最终采用的配置模板:

name: Deploy to GitHub Pages
# 触发条件:当推送到 main 分支时
on:
push:
branches:
- main
# 可以根据需要添加路径过滤,比如只有文档变动才构建
# paths:
# - 'docs/**'
# - 'package.json'
# 设置权限,这对于部署到 GitHub Pages 很重要
permissions:
contents: read
pages: write
id-token: write
# 并发控制:取消同一分支的旧构建
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# 注意:必须设置 fetch-depth: 0,否则可能导致构建版本号不准确
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20 # 建议与本地开发环境保持一致
cache: 'npm' # 启用缓存可以加速构建过程
- name: Install dependencies
run: npm ci
# 使用 npm ci 而不是 npm install,因为它更快、更严格,适合 CI 环境
- name: Build website
run: npm run build
env:
# 如果你的站点构建需要环境变量,在这里配置
# NODE_ENV: production
# PUBLIC_URL: /your-repo-name
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./build # Docusaurus 默认输出目录
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

在实际操作中,我们遇到了一些问题,这里分享出来希望大家能避开(或者提前准备好解决方案)。

最开始配置的时候,部署总是报错 403 (Forbidden)。查了好久才发现,是因为 GitHub 默认的 GITHUB_TOKEN 并没有写入 Pages 的权限。

解决方案:在仓库的 Settings -> Actions -> General -> Workflow permissions 中,务必选择 “Read and write permissions”

Docusaurus 默认把构建好的静态文件放在 build 目录。但是有些项目(比如 Create React App 默认是 build,Vite 默认是 dist)可能配置不一样。如果在 Actions 中报错找不到文件,记得去 docusaurus.config.js 里检查一下输出路径配置。

如果你的仓库不是用户主页(即不是 username.github.io),而是项目主页(比如 username.github.io/project-name),你需要配置 baseUrl

docusaurus.config.js 中:

module.exports = {
// ...
url: 'https://hagicode.com', // 你的 Hagicode URL
baseUrl: '/', // 根路径部署
// ...
};

这一点很容易被忽略,配置不对会导致页面打开全是白屏,因为资源路径加载不到。

配置完所有东西并推送代码后,我们就可以去 GitHub 仓库的 Actions 标签页看戏了。

你会看到黄色的圆圈(工作流正在运行),变绿就代表成功啦!如果变红了,点击进去查看日志,通常都能排查出问题(大部分时候是拼写错误或者路径配置不对)。

构建成功后,访问 https://<你的用户名>.github.io/<仓库名>/ 就能看到崭新的站点了。

通过引入 GitHub Actions,我们成功实现了 HagiCode 文档站的自动化部署。这不仅节省了手动操作的时间,更重要的是保证了发布流程的标准化。现在不管是哪位小伙伴更新了文档,只要合并到 main 分支,几分钟后就能在线上看到最新的内容。

核心收益

  • 效率提升:从”手动打包、手动上传”变成”代码即发布”。
  • 降低错误:消除了人为操作失误的可能性。
  • 体验优化:让开发者更专注于内容质量,而不是被繁琐的部署流程困扰。

虽然配置 CI/CD 刚开始有点麻烦(尤其是各种权限和路径问题),但这是一次性投入,长期回报巨大的工作。强烈建议所有静态站点项目都接入类似的自动化流程。


感谢您的阅读,如果您觉得本文有用,快点击下方点赞按钮👍,让更多的人看到本文。

本内容采用人工智能辅助协作,经本人审核,符合本人观点与立场。

如何使用 GitHub Actions + image-syncer 实现 Docker Hub 到 Azure ACR 的自动化镜像同步

实现 Docker Hub 到 Azure ACR 的自动化镜像同步

Section titled “实现 Docker Hub 到 Azure ACR 的自动化镜像同步”

本文介绍了如何使用 GitHub Actions 和 image-syncer 工具,实现 Docker Hub 镜像到 Azure Container Registry 的自动化同步,解决了国内及部分 Azure 区域访问 Docker Hub 速度慢的问题,提升了镜像的可用性和 Azure 环境的部署效率。

HagiCode 项目使用 Docker 镜像作为核心运行时组件,主要镜像托管在 Docker Hub。随着项目发展和 Azure 环境部署需求的增加,我们遇到了以下痛点:

  • 镜像拉取速度慢,Docker Hub 在国内及部分 Azure 区域访问受限
  • 依赖单一镜像源存在单点故障风险
  • Azure 环境下使用 Azure Container Registry 能获得更好的网络性能和集成体验

为解决这些问题,我们需要建立一个自动化的镜像同步机制,将 Docker Hub 的镜像定期同步到 Azure ACR,确保用户能够在 Azure 环境中获得更快的镜像拉取速度和更高的可用性。

我们正在开发 HagiCode——一款 AI 驱动的代码智能助手,让开发体验变得更智能、更便捷、更有趣。

智能——AI 全程辅助,从想法到代码,让编码效率提升数倍。便捷——多线程并发操作,充分利用资源,开发流程顺畅无阻。有趣——游戏化机制和成就系统,让编码不再枯燥,充满成就感。

项目正在快速迭代中,如果你对技术写作、知识管理或者 AI 辅助开发感兴趣,欢迎来 GitHub 看看。

在制定解决方案时,我们对比了多种技术方案:

  • 增量同步:仅同步变更的镜像层,显著减少网络传输
  • 断点续传:网络中断后可恢复同步
  • 并发控制:支持配置并发线程数,提升大镜像同步效率
  • 完善的错误处理:内置失败重试机制(默认 3 次)
  • 轻量级部署:单二进制文件,无依赖
  • 多仓库支持:兼容 Docker Hub、Azure ACR、Harbor 等
  • 不支持增量同步:每次都需要拉取完整的镜像内容
  • 效率较低:网络传输量大,时间长
  • 简单易用:使用熟悉的 docker pull/push 命令
  • 复杂度高:需要配置 Azure CLI 认证
  • 功能限制:az acr import 功能相对单一
  • 原生集成:与 Azure 服务集成良好

决策 1:同步频率设置为每日 UTC 00:00

Section titled “决策 1:同步频率设置为每日 UTC 00:00”
  • 平衡镜像新鲜度和资源消耗
  • 避开业务高峰期,减少对其他操作的影响
  • Docker Hub 镜像通常在每日构建后更新
  • 保持与 Docker Hub 的完全一致性
  • 为用户提供灵活的版本选择
  • 简化同步逻辑,避免复杂的标签过滤规则

决策 3:使用 GitHub Secrets 存储认证信息

Section titled “决策 3:使用 GitHub Secrets 存储认证信息”
  • GitHub Actions 原生支持,安全性高
  • 配置简单,易于管理和维护
  • 支持仓库级别的访问控制
  • 使用 GitHub Secrets 加密存储
  • 定期轮换 ACR 密码
  • 限制 ACR 用户权限为仅推送
  • 监控 ACR 访问日志

风险 2:同步失败导致镜像不一致

Section titled “风险 2:同步失败导致镜像不一致”
  • image-syncer 内置增量同步机制
  • 自动失败重试(默认 3 次)
  • 详细的错误日志和失败通知
  • 断点续传功能
  • 增量同步减少网络传输
  • 可配置并发线程数(当前设置为 10)
  • 监控同步的镜像数量和大小
  • 在非高峰时段运行同步

我们采用 GitHub Actions + image-syncer 的自动化方案,实现从 Docker Hub 到 Azure ACR 的镜像同步。

  • 在 Azure Portal 中创建或确认 Azure Container Registry
  • 创建 ACR 访问密钥(用户名和密码)
  • 确认 Docker Hub 镜像仓库访问权限

在 GitHub 仓库设置中添加以下 Secrets:

  • AZURE_ACR_USERNAME: Azure ACR 用户名
  • AZURE_ACR_PASSWORD: Azure ACR 密码

在 .github/workflows/sync-docker-acr.yml 中配置工作流:

  • 定时触发:每天 UTC 00:00
  • 手动触发:支持 workflow_dispatch
  • 额外触发:publish 分支推送时触发(用于快速同步)
顺序参与方动作说明
1GitHub Actions触发工作流由定时、手动或 publish 分支推送触发
2GitHub Actions → image-syncer下载并执行同步工具进入实际同步阶段
3image-syncer → Docker Hub获取镜像 manifest 与标签列表读取源仓库元数据
4image-syncer → Azure ACR获取目标仓库已存在镜像信息判断目标侧当前状态
5image-syncer对比源与目标差异识别需要同步的镜像层
6image-syncer → Docker Hub拉取变更的镜像层仅传输需要更新的内容
7image-syncer → Azure ACR推送变更的镜像层完成增量同步
8image-syncer → GitHub Actions返回同步统计信息包含结果、差异和错误信息
9GitHub Actions记录日志并上传 artifact便于后续审计与排查

以下是实际运行的工作流配置(.github/workflows/sync-docker-acr.yml):

name: Sync Docker Image to Azure ACR
on:
schedule:
- cron: "0 0 * * *" # 每天 UTC 00:00
workflow_dispatch: # 手动触发
push:
branches: [publish]
permissions:
contents: read
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download image-syncer
run: |
# 下载 image-syncer 二进制文件
wget https://github.com/AliyunContainerService/image-syncer/releases/download/v1.5.5/image-syncer-v1.5.5-linux-amd64.tar.gz
tar -zxvf image-syncer-v1.5.5-linux-amd64.tar.gz
chmod +x image-syncer
- name: Create auth config
run: |
# 生成认证配置文件 (YAML 格式)
cat > auth.yaml <<EOF
hagicode.azurecr.io:
username: "${{ secrets.AZURE_ACR_USERNAME }}"
password: "${{ secrets.AZURE_ACR_PASSWORD }}"
EOF
- name: Create images config
run: |
# 生成镜像同步配置文件 (YAML 格式)
cat > images.yaml <<EOF
docker.io/newbe36524/hagicode: hagicode.azurecr.io/hagicode
EOF
- name: Run image-syncer
run: |
# 执行同步 (使用新版 --auth 和 --images 参数)
./image-syncer --auth=./auth.yaml --images=./images.yaml --proc=10 --retries=3
- name: Upload logs
if: always()
uses: actions/upload-artifact@v4
with:
name: sync-logs
path: image-syncer-*.log
retention-days: 7
  • 定时触发:cron: “0 0 * * *” - 每天 UTC 00:00 执行
  • 手动触发:workflow_dispatch - 允许用户在 GitHub UI 手动运行
  • 推送触发:push: branches: [publish] - 发布分支推送时触发(用于快速同步)
hagicode.azurecr.io:
username: "${{ secrets.AZURE_ACR_USERNAME }}"
password: "${{ secrets.AZURE_ACR_PASSWORD }}"
docker.io/newbe36524/hagicode: hagicode.azurecr.io/hagicode

此配置表示将 docker.io/newbe36524/hagicode 的所有标签同步到 hagicode.azurecr.io/hagicode

  • —auth=./auth.yaml: 认证配置文件路径
  • —images=./images.yaml: 镜像同步配置文件路径
  • —proc=10: 并发线程数为 10
  • —retries=3: 失败重试 3 次

在 GitHub 仓库的 Settings → Secrets and variables → Actions 中配置:

Secret 名称描述示例值获取方式
AZURE_ACR_USERNAMEAzure ACR 用户名hagicodeAzure Portal → ACR → Access keys
AZURE_ACR_PASSWORDAzure ACR 密码xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxAzure Portal → ACR → Access keys → Password
  1. 访问 GitHub 仓库的 Actions 标签页
  2. 选择 Sync Docker Image to Azure ACR 工作流
  3. 点击 Run workflow 按钮
  4. 选择分支并点击 Run workflow 确认
  1. 在 Actions 页面点击具体的工作流运行记录
  2. 查看各个步骤的执行日志
  3. 在页面底部的 Artifacts 区域下载 sync-logs 文件
Terminal window
# 登录到 Azure ACR
az acr login --name hagicode
# 列出镜像及其标签
az acr repository show-tags --name hagicode --repository hagicode --output table
  • 定期轮换 Azure ACR 密码(建议每 90 天)
  • 使用专用的 ACR 服务账户,限制权限为仅推送
  • 监控 ACR 的访问日志,及时发现异常访问
  • 不要在日志中输出认证信息
  • 不要将认证信息提交到代码仓库
  • 调整 —proc 参数:根据网络带宽调整并发数(建议 5-20)
  • 监控同步时间:如果同步时间过长,考虑减少并发数
  • 定期清理日志:设置合理的 retention-days(当前为 7 天)
Error: failed to authenticate to hagicode.azurecr.io

解决方案:

  1. 检查 GitHub Secrets 是否正确配置
  2. 验证 Azure ACR 密码是否过期
  3. 确认 ACR 服务账户权限是否正确
Error: timeout waiting for response

解决方案:

  1. 检查网络连接
  2. 减少并发线程数(—proc 参数)
  3. 等待网络恢复后重新触发工作流
Warning: some tags failed to sync

解决方案:

  1. 检查同步日志,识别失败的标签
  2. 手动触发工作流重新同步
  3. 验证 Docker Hub 源镜像是否正常
  • 定期检查 Actions 页面,确认工作流运行状态
  • 设置 GitHub 通知,及时获取工作流失败通知
  • 监控 Azure ACR 的存储使用情况
  • 定期验证镜像标签一致性

Q1: 如何同步特定标签而不是所有标签?

Section titled “Q1: 如何同步特定标签而不是所有标签?”

修改 images.yaml 配置文件:

# 仅同步 latest 和 v1.0 标签
docker.io/newbe36524/hagicode:latest: hagicode.azurecr.io/hagicode:latest
docker.io/newbe36524/hagicode:v1.0: hagicode.azurecr.io/hagicode:v1.0

在 images.yaml 中添加多行配置:

docker.io/newbe36524/hagicode: hagicode.azurecr.io/hagicode
docker.io/newbe36524/another-image: hagicode.azurecr.io/another-image
  • 自动重试:image-syncer 内置重试机制(默认 3 次)
  • 手动重试:在 GitHub Actions 页面点击 Re-run all jobs
  • 在 Actions 页面查看实时日志
  • 下载 sync-logs artifact 查看完整日志文件
  • 日志文件包含每个标签的同步状态和传输速度
  • 首次全量同步:根据镜像大小,通常需要 10-30 分钟
  • 增量同步:如果镜像变更小,通常 2-5 分钟
  • 时间取决于网络带宽、镜像大小和并发设置

在工作流中添加通知步骤:

- name: Notify on success
if: success()
run: |
echo "Docker images synced successfully to Azure ACR"

在工作流中添加标签过滤逻辑:

- name: Filter tags
run: |
# 仅同步以 v 开头的标签
echo "docker.io/newbe36524/hagicode:v* : hagicode.azurecr.io/hagicode:v*" > images.yaml
- name: Generate report
if: always()
run: |
echo "## Sync Report" >> $GITHUB_STEP_SUMMARY
echo "- Total tags: $(grep -c 'synced' image-syncer-*.log)" >> $GITHUB_STEP_SUMMARY
echo "- Sync time: ${{ steps.sync.outputs.duration }}" >> $GITHUB_STEP_SUMMARY

通过本文介绍的方法,我们成功实现了从 Docker Hub 到 Azure ACR 的自动化镜像同步。这个方案利用 GitHub Actions 的定时触发和手动触发功能,结合 image-syncer 的增量同步和错误处理机制,确保了镜像的及时同步和一致性。

我们还讨论了安全最佳实践、性能优化、故障排查等方面的内容,帮助用户更好地管理和维护这个同步机制。希望本文能够为需要在 Azure 环境中部署 Docker 镜像的开发者提供有价值的参考。


感谢您的阅读,如果您觉得本文有用,快点击下方点赞按钮👍,让更多的人看到本文。

本内容采用人工智能辅助协作,经本人审核,符合本人观点与立场。