超快路径

代码仓库:github repo 可以直接fork, 然后设置按照 5.2 配置 Secrets即可

前言

作为国内开发者和运维人员,我们正面临一个日益严峻的挑战:曾经是全球 Docker 镜像中心的 Docker Hub,如今在国内的访问变得异常艰难,甚至完全无法连接。那些曾经为我们提供便利的公共 Docker 镜像加速器,也大多已失去其加速作用,沦为历史。

这不仅仅是下载速度慢的问题,更是 CI/CD 流水线中断、开发效率骤降的根本原因。每一次 docker pull 的超时,每一次 docker build 的失败,都在无情地消耗着我们的耐心和项目进度。

本文将提供一个稳定、高效且完全自动化的解决方案,帮助你彻底摆脱这一困境。我们将利用 GitHub Actions 的全球化执行能力作为“桥梁”,将所需的 Docker 镜像自动化同步到国内可高速访问的 阿里云容器镜像服务 (ACR)。告别网络延迟,享受丝滑的 Docker 体验!


1. 引言

1.1 当 Docker 镜像加速节点成为“历史”

在国内进行 Docker 开发和 CI/CD,一个令人头疼的现实是:曾经赖以生存的 Docker Hub 及其他海外镜像源,现在变得越来越难以访问。曾经寄予厚望的各类公共 Docker 镜像加速器(如 DaoCloud、Ustc 等)也大多已成往事,其稳定性和速度已无法满足日常开发和生产环境的需求。

这意味着什么?这意味着你的 docker pull 命令可能长时间卡顿,docker build 任务屡次失败,CI/CD 流水线因基础镜像无法拉取而被迫中断。这些并非短暂的网络波动,而是长期困扰国内开发者和企业用户的普遍性挑战,严重拖慢了项目进度,消耗了宝贵的开发时间。

1.2 构建你的专属高速镜像通道

那么,有没有一个兼顾稳定、高效、自动化,并且符合国内网络环境特点的解决方案呢?

本文将为你揭示并详细实践一个行之有效的方法:利用 GitHub Actions 的全球化执行环境作为“中转站”,将所需的 Docker 镜像自动化同步到国内高速可达的 阿里云容器镜像服务 (ACR)。这不仅能彻底解决镜像拉取慢、无法访问的问题,还能为你的 CI/CD 流水线注入前所未有的稳定性和速度。

1.3 摆脱困境,畅享 Docker 开发

通过阅读本文,你将学会如何:

  • 配置 GitHub Actions 与 Aliyun ACR 的无缝集成,搭建安全可靠的自动化通道。
  • 编写并优化自动化 Workflow,实现指定 Docker 镜像的基于配置更新或手动同步。
  • 为自己或团队构建一个稳定、高速且完全可控的国内 Docker 镜像缓存,彻底摆脱对外部镜像源的依赖。

告别焦急的等待和失败的构建,让我们一起动手,为你的 Docker 开发和 CI/CD 流程重新焕发活力!


2. 问题分析与传统解决方案的局限性

在探讨解决方案之前,我们有必要深入剖析 Docker 镜像访问困境的根源,并理解为什么传统方案已无法满足当前需求。

2.1 Docker 镜像访问困境的根源

  • 国际网络环境复杂: 国内与海外的网络连接受多种因素影响,导致对 Docker Hub、Quay.io、Google Container Registry (GCR.io) 等主流海外镜像源的访问不稳定,时常出现连接中断、速度缓慢等问题。
  • CI/CD 流水线受阻: 在自动化构建和部署场景中,基础镜像的拉取是第一步。一旦这一步失败,整个流水线将无法继续,导致频繁的构建失败和部署延迟,严重影响开发和交付效率。
  • 公共加速器失效: 过去,一些国内的公共 Docker 镜像加速器曾提供便利。然而,由于政策、维护成本或网络环境变化等原因,这些加速器大多已停止服务或效果甚微,不再能提供可靠的加速服务。

2.2 传统解决方案的局限性

面对上述挑战,开发者们曾尝试过多种方案,但它们往往存在各自的局限性:

  • 手动下载与导入 (docker save/docker load):
    • 弊端: 极其繁琐,无法自动化,不适用于频繁更新的镜像和 CI/CD 场景。
  • 配置 Docker 镜像加速器(如 DaoCloud、Ustc 等):
    • 弊端: 多数已失效或速度不佳,无法提供长期稳定的保障。
  • 企业内部搭建 Registry 或 Proxy:
    • 弊端: 成本高昂(需要服务器资源和维护人力),部署复杂,且其自身仍然需要解决拉取上游镜像的问题。
  • VPN/代理:
    • 弊端: 不稳定,速度受限,部分存在合规性和法律风险,最重要的是,难以在无头(Headless)的 CI/CD 环境中稳定、安全地集成和运行。

正是这些传统方案的力不从心,促使我们寻找一个更稳定、高效、自动化且符合国内网络环境的最佳实践。


3. 解决方案概览:GitHub Actions + Aliyun ACR

在深入实践之前,我们首先需要理解这个解决方案的核心理念,以及它如何巧妙地规避现有难题,从而带来显著的优势。

3.1 核心理念:跨越网络屏障,构建高速缓存

我们的方案基于以下两个关键组件的协同作用:

  1. GitHub Actions 作为“跳板”/“中转站”: GitHub Actions 的执行环境(即 Runner)通常部署在全球各地,特别是海外数据中心。这意味着,GitHub Actions 的 Runner 拥有直接、高速访问 Docker Hub 或其他海外 Docker 镜像源的能力,不受国内网络环境的直接影响。我们正是利用这一点,让 GitHub Actions 代劳,从那些难以访问的源头拉取所需的 Docker 镜像。它就像是你部署在海外的一个“自动化代理”,专门为你去“搬运”镜像。

  2. Aliyun ACR 作为“国内高速缓存”: 阿里云容器镜像服务 (ACR) 是阿里云提供的稳定、高性能的容器镜像管理服务。其所有服务节点都部署在中国境内。一旦 GitHub Actions Runner 成功从 Docker Hub 拉取到镜像,我们就可以将其推送到你的专属 ACR 仓库中。这样,当你或你的国内 CI/CD 环境需要这些镜像时,可以直接从国内的 ACR 高速拉取,彻底摆脱了国际网络瓶颈的困扰。ACR 在这里扮演的角色,是一个持久化、高可用的“本地化镜像缓存”。

  3. 自动化:一劳永逸的同步机制: 整个同步过程可以通过 GitHub Actions 的灵活触发机制(例如代码推送 push 来触发,尤其是当你更新 images.txt 配置时,或手动触发 workflow_dispatch)来实现高度自动化。一旦配置完成,你只需更新配置文件或手动点击,系统即可自动检查并同步最新的镜像版本。这大大减少了人工维护成本,并确保了镜像的及时更新和可用性。

3.2 流程图

graph TD
    subgraph Docker 镜像源
        D[Docker Hub / Quay.io / GCR.io / 其他源]
    end

    subgraph 触发机制
        E[代码提交 / images.txt更新] -- Git Push 触发 --> C
        G[手动触发 workflow_dispatch] -- 用户点击 --> C
    end

    subgraph 镜像同步流程
        C(GitHub Actions Runner <br/> 海外服务器)
        D -- 海外网络拉取 --> C
        C -- GitHub Actions 推送 --> B(阿里云 ACR 个人版)
    end

    subgraph 国内使用
        A[开发者 / 国内CI/CD] -- 国内高速拉取 --> B
    end

3.3 方案优势:免费、稳定、自动化

通过 GitHub Actions 和 Aliyun ACR 的强强联合,我们的方案具备以下显著优势:

  1. 成本效益:

    • GitHub Actions: 提供慷慨的免费额度(每月 2000 分钟的 Linux Runner),对于个人项目和小型团队而言,通常足以满足日常同步需求。
    • Aliyun ACR: 个人版提供基础功能免费额度,包括一定的存储空间和公网下行流量,对于存储少量常用镜像来说,通常费用极低甚至免费。超出额度或使用高级功能才会产生费用。
  2. 稳定可靠: 该方案巧妙地将“海外拉取”和“国内分发”解耦,各司其职。GitHub Actions 解决了国际网络访问问题,ACR 提供了国内高速分发能力。这从根本上绕开了困扰国内开发者的网络限制,确保了镜像访问的稳定性和可靠性,避免了因网络波动或加速器失效导致的构建中断。

  3. 高度自动化: 利用 GitHub Actions 的自动化能力,你可以通过更新配置或手动触发来同步镜像,确保你的镜像库始终保持最新状态,让你能够“设置一次,按需同步”。

  4. 易于部署与维护: GitHub Actions 和 Aliyun ACR 都是成熟的云服务和 CI/CD 工具,拥有完善的文档和友好的用户界面。你无需搭建复杂的私有镜像代理服务器或维护底层的基础设施,大大降低了部署和后期维护的复杂度和成本。

  5. 极佳的可扩展性: 通过简单的配置文件(images.txt),你可以轻松添加、删除或修改需要同步的镜像。无论少量核心镜像还是大量项目依赖,该方案都能灵活应对,方便你根据实际需求进行扩展。

  6. 增强的安全性与控制: 你的镜像最终存储在专属的 Aliyun ACR 仓库中,你可以对这些镜像进行精细的权限管理。GitHub Secrets 的使用也确保了认证信息的安全存储。


4. Aliyun ACR 设置

4.1 开通服务

访问阿里云容器镜像服务控制台,如果首次使用,按照指引开通“个人版”实例。个人版实例目前提供免费的存储空间,对于个人和小团队来说基本够用。

4.2 设置访问凭证

ACR 个人版实例,可以设置一个固定密码用于 Docker CLI 登录。进入你的个人版实例,在左侧导航栏找到“访问凭证”或类似选项,设置一个固定的登录密码。

4.3 创建命名空间 (Namespace)

命名空间用于组织你的镜像。在你的 ACR 实例中,创建一个新的命名空间,例如 my-images 或你的项目名。

4.4 记下你的 ACR 实例的信息

  • Registry 地址通常是:registry.cn-hangzhou.aliyuncs.com (根据你选择的地域可能不同)
  • 命名空间:3.3中创建的命名空间
  • 用户名:访问凭证中的username
  • 密码:你设置的固定密码

5. GitHub 仓库及 Secrets 配置

5.1. 创建 GitHub 仓库:

如果你还没有专门的仓库,可以创建一个新的 GitHub 仓库 (可以是私有的) 来存放我们的 Workflow 文件。例如,docker-image-sync

5.2 配置 Secrets

为了安全地在 GitHub Actions 中使用阿里云 ACR 的凭证,我们需要将它们配置为仓库的 Secrets。切勿将密码等敏感信息直接硬编码到 Workflow 文件中! 进入你的 GitHub 仓库页面,点击 “Settings” “Secrets and variables” “Actions”。然后点击 “New repository secret” 添加以下 Secrets:

  • ACR_USERNAME: 前面Aliyun ACR中的用户名
  • ACR_PASSWORD: 前面Aliyun ACR设置的固定密码
  • ACR_REGISTRY: 前面Aliyun ACR中的Registry
  • ACR_NAMESPACE: 前面Aliyun ACR中创建的命名空间

6. 核心步骤:配置 GitHub Workflow

6.1 拉取 GitHub 创建的仓库代码

首先,将你刚刚在 GitHub 上创建的空仓库克隆到本地:

git clone <你的 GitHub 仓库地址>

6.2 创建 Workflow 文件和配置

接下来,在克隆到本地的仓库中创建所需的文件和目录。最终目录结构如下:

docker-image-sync/
├── .github/
│   └── workflows/
│       └── sync.yml        # GitHub Actions Workflow 定义文件
├── README.md               # 仓库说明文件
├── config.env              # 镜像同步配置(ACR Registry地址和命名空间)
├── images.txt              # 需要同步的 Docker 镜像列表
└── sync.sh                 # 实际执行镜像同步的 Shell 脚本

6.3 编写 sync.yml (GitHub Workflow)

将以下内容粘贴到 .github/workflows/sync.yml 文件中。这个 Workflow 定义了何时触发镜像同步以及具体执行哪些步骤。

name: Sync Docker Images to Aliyun ACR # Workflow 的名称
run-name: ${{ github.actor }} is syncing Docker images # 在 GitHub Actions 页面显示运行者
on:
  push: # 当有代码推送到以下分支或路径时触发
    branches:
      - main # 监听 main 分支的推送
    paths:
      - 'images.txt' # 只有 images.txt 文件更新才触发
      - '.github/workflows/sync.yml' # workflow 文件自身更新也触发
  workflow_dispatch: # 允许手动触发 Workflow
  
jobs:
  sync-images: # 定义一个 Job
    runs-on: ubuntu-latest # GitHub Actions Runner 运行环境 (Ubuntu 最新版)
    steps:
      - name: Checkout repository # 步骤1: 拉取 GitHub 仓库代码
        uses: actions/checkout@v4 # 使用 actions/checkout@v4 action
      
      - name: Login to Aliyun Container Registry (ACR) # 步骤2: 登录 ACR
        uses: docker/login-action@v3 # 使用 docker/login-action@v3 action
        with:
          registry: ${{ secrets.ACR_REGISTRY }} # 动态构建 ACR Registry 地址
          username: ${{ secrets.ACR_USERNAME }} # 使用 GitHub Secrets 中的 ACR 用户名 (RAM AccessKey ID)
          password: ${{ secrets.ACR_PASSWORD }} # 使用 GitHub Secrets 中的 ACR 密码 (RAM AccessKey Secret)
          
      - name: Execute sync script # 步骤3: 执行同步脚本
        run: |
          bash "${{ github.workspace }}/sync.sh" # 运行 sync.sh 脚本
        env:
          ACR_REGISTRY: ${{ secrets.ACR_REGISTRY }}
          ACR_NAMESPACE: ${{ secrets.ACR_NAMESPACE }}
        
      - name: Job status # 步骤4 (可选): 打印 Job 状态
        run: echo "This job's status is ${{ job.status }}"

6.4 编写 images.txt (同步镜像列表)

将以下内容粘贴到 images.txt 文件中。每一行代表一个需要同步的 Docker 镜像,格式为 镜像名:标签

特别注意:此文件最后一定要有一行空行,以确保 Shell 脚本能完整读取所有行。

# 官方镜像示例
nginx:1.28.0
ubuntu:22.04
python:3.9-slim

# 此处一定要有一行空行

6.5 编写 sync.sh (核心同步脚本)

将以下内容粘贴到 sync.sh 文件中。这个脚本会读取 images.txt 中的列表,逐一拉取镜像,打上 ACR 标签,并推送到你的 ACR 仓库。脚本中包含判重逻辑

#!/bin/bash
set -eux # -u: 遇到未定义变量报错;-e: 任何命令失败立即退出;-x: 打印执行的命令
 
IMAGES_FILE="images.txt"
 
# 检查配置文件和镜像列表文件是否存在
if [ ! -f "$IMAGES_FILE" ]; then
    echo "Error: images.txt not found! Please create it with a list of images to sync."
    exit 1
fi
 
 
# 检查必要的配置变量是否已设置
if [ -z "$ACR_REGISTRY" ] || [ -z "$ACR_NAMESPACE" ]; then
    echo "Error: ACR_REGISTRY or ACR_NAMESPACE not set in github variables. Please check your config."
    exit 1
fi
 
echo "Starting Docker image synchronization to ACR..."
echo "Target Registry: ${ACR_REGISTRY}"
echo "Target Namespace: ${ACR_NAMESPACE}"
echo "-----------------------------------"
 
# 遍历 images.txt,逐行处理镜像
while IFS= read -r image; do
    # 跳过空行或以 # 开头的注释行
    if [[ -z "$image" || "$image" =~ ^# ]]; then
        continue
    fi
 
    echo "--- Processing image: ${image} ---"
 
    # 分离原始镜像的仓库名和标签
    # 例如:nginx:latest -> original_repo=nginx, original_tag=latest
    # 例如:jenkins/jenkins:lts -> original_repo=jenkins/jenkins, original_tag=lts
    original_repo=$(echo "$image" | cut -d ':' -f1)
    original_tag=$(echo "$image" | cut -d ':' -f2)
 
    # 构造目标 ACR 完整镜像路径
    target_full_image_path="${ACR_REGISTRY}/${ACR_NAMESPACE}/${original_repo}:${original_tag}"
 
    echo "Original image full path: ${image}"
    echo "Target ACR image full path: ${target_full_image_path}"
 
    # 检查阿里云仓库是否已有该tag
    # docker manifest inspect 命令用于检查远程 Registry 中的镜像是否存在。
    # 如果已经存在,则跳过本次同步,避免重复操作和不必要的流量消耗。
    if docker manifest inspect "${target_full_image_path}" > /dev/null 2>&1; then
        echo "${target_full_image_path} 已存在于 ACR,跳过本次同步。"
        echo "-----------------------------------"
        continue # 跳过当前循环的后续步骤
    fi
 
    echo "Image ${target_full_image_path} not found in ACR. Proceeding with sync..."
 
    # 拉取原始镜像
    echo "Pulling original image: ${image}..."
    docker pull "${image}"
 
    # 打上阿里云 ACR 的标签
    echo "Tagging image ${image} to ${target_full_image_path}..."
    docker tag "${image}" "${target_full_image_path}"
 
    # 推送到阿里云 ACR
    echo "Pushing image ${target_full_image_path} to ACR..."
    docker push "${target_full_image_path}"
 
    # 清理本地拉取和打标签的镜像,释放 GitHub Actions Runner 的磁盘空间
    echo "Cleaning up local images..."
    # 使用 || true 即使删除失败也不会中断脚本,确保后续镜像能继续处理
    docker rmi "${image}" || true
    docker rmi "${target_full_image_path}" || true
 
    echo "Successfully synced: ${image} to ${target_full_image_path}"
    echo "-----------------------------------"
 
done < "$IMAGES_FILE"
 
echo "All specified images processed successfully."
echo "Synchronization process finished."

6.6 提交代码到 GitHub 仓库

完成文件创建和内容粘贴后,将这些文件提交到你的 GitHub 仓库:

git add .
git commit -m "Add workflow to sync Docker images to ACR"
git push origin main

6.7 查看GitHub Actions同步状态

代码推送后,GitHub Actions 将根据 sync.yml 中定义的触发器(push 或手动 workflow_dispatch)自动运行 Workflow。

你可以在 GitHub 仓库页面的 “Actions” 选项卡中查看 Workflow 的运行状态和日志。

6.8 Aliyun ACR查看镜像同步结果

当 Workflow 成功运行后,你可以登录到 Aliyun ACR 控制台,进入你的命名空间,查看已同步的镜像。

6.9 后期增加镜像同步

后续需要同步新的镜像时,只需修改 images.txt 文件,在其中添加新的镜像名和标签,然后提交到 GitHub 仓库即可。GitHub Actions 会自动检测 images.txt 的变更并触发同步。

脚本会自动判重:如果 ACR 中已经存在相同 acr_repo_name:original_tag 的镜像,脚本会跳过该镜像的同步。这意味着你可以保留 images.txt 中已同步的镜像,无需手动清理。如果需要强制更新某个镜像(即使标签相同,内容可能已更新),你需要手动从 ACR 中删除旧的镜像,或者修改 sync.sh 脚本的判重逻辑。


7. 使用 Aliyun ACR 镜像

一旦镜像成功同步到 Aliyun ACR,你就可以在你的本地开发环境或国内的 CI/CD 流水线中,高速、稳定地拉取这些镜像。

7.1 登录阿里云 ACR:

docker login --username=your_name registry.cn-hangzhou.aliyuncs.com
# 详见设置访问凭证中的docker login

7.2 拉取镜像:

根据你在 `images.txt` 中配置的原始镜像名,以及 `sync.sh` 脚本的命名转换规则(将 `/` 替换为 `-`),构造完整的 ACR 镜像路径进行拉取。

例如,如果你同步了 `langgenius/dify-api:1.3.0`:

```shell
# 对于 langgenius/dify-api:1.3.0,ACR 中的名称会变成 langgenius-dify-api:1.3.0
# 请将 your_namespace 替换为你在 ACR 中创建的命名空间
docker pull registry.cn-hangzhou.aliyuncs.com/your_namespace/langgenius-dify-api:1.3.0
```

如果同步了 `nginx:1.28.0`:

```shell
docker pull registry.cn-hangzhou.aliyuncs.com/your_namespace/nginx:1.28.0
```

7.2 (可选但推荐) 创建本地 Tag,以便在 Dockerfile 或 docker-compose.yml 中使用原始镜像名:

如果你希望在 Dockerfile 中继续使用 FROM langgenius/dify-api:1.3.0 这样的原始镜像名,或者在 docker-compose.yml 中直接引用,你可以在拉取到 ACR 镜像后,为它创建一个本地 Tag。

# 假设你已经成功拉取了 ACR 镜像
# docker pull registry.cn-hangzhou.aliyuncs.com/your_namespace/langgenius-dify-api:1.3.0
 
# 创建一个指向本地 ACR 镜像的原始名称 Tag
docker tag registry.cn-hangzhou.aliyuncs.com/your_namespace/langgenius-dify-api:1.3.0 langgenius/dify-api:1.3.0
 
# 现在你就可以像往常一样使用原始名称了
docker run --rm langgenius/dify-api:1.3.0 ...

通过这种方式,你可以最大程度地减少对现有项目配置的修改。


8. 进阶考量与最佳实践

为了使你的镜像同步方案更加健壮和高效,可以考虑以下进阶实践:

8.1 镜像标签策略

  • 避免过度同步 latest 尽管 latest 标签方便,但它可能指向不同版本的镜像,在生产环境中带来不确定性。建议优先同步特定版本号的镜像(例如 nginx:1.23.0),以确保环境的可复现性。
  • 多标签镜像处理: 如果一个镜像有多个标签(例如 ubuntu:latestubuntu:22.04),它们可能指向相同的底层镜像层,但为了完整性,你需要在 images.txt 中分别列出它们。

8.2 同步触发与资源消耗

  • 合理利用 pushworkflow_dispatch
    • push 触发适合当你需要同步新镜像或更新现有镜像列表时,通过代码提交自动触发。
    • workflow_dispatch 适合进行即时、手动的同步操作,例如紧急需要某个新镜像时。
  • 关注 GitHub Actions 免费额度: GitHub Actions 提供免费额度(每月 2000 分钟的 Linux Runner)。你可以通过 GitHub 账户设置查看使用情况。如果你的同步镜像数量庞大,可能需要考虑升级 GitHub 付费计划。

8.3 安全性

  • GitHub Secrets 保护: 确保你的 GitHub Secrets 仅供授权的 Workflow 使用,不要在 Workflow 日志中打印这些敏感信息。

8.4 错误处理与通知

  • Workflow 失败通知: 配置 GitHub Actions 在 Workflow 失败时发送通知。你可以通过 GitHub 邮件通知、或集成第三方服务(如 Slack、钉钉、企业微信)来接收失败提醒,以便及时介入处理。
  • 日志分析: 当同步失败时,仔细分析 GitHub Actions 的运行日志。sync.sh 中的 set -eux 会打印详细的执行命令和错误信息,帮助你快速定位问题。

8.5 自定义镜像的构建与推送

  • 基于 ACR 的基础镜像: 如果你的项目 Dockerfile 中使用的基础镜像来自 Docker Hub,现在你可以将其 FROM 指令修改为从 ACR 拉取,例如 FROM registry.cn-hangzhou.aliyuncs.com/your_namespace/ubuntu:22.04
  • 在 GitHub Actions 中构建并推送自定义镜像: 如果你的项目也需要构建自己的 Docker 镜像,并且 Dockerfile 也存在于 GitHub 仓库中,你可以利用 docker/build-push-action 直接在同一个 GitHub Actions Workflow 中构建你的自定义镜像,并推送到 Aliyun ACR。

9. 总结

本文为你提供了一个强大而实用的解决方案,旨在彻底解决国内 Docker 镜像访问受限的痛点。通过巧妙地结合 GitHub Actions 的全球化执行能力和阿里云 ACR 的国内高速分发网络,我们成功地构建了一个自动化、稳定、高效的 Docker 镜像同步通道。

从现在开始,你将告别因网络问题导致的 docker pull 失败和 CI/CD 流水线中断。你的开发环境将拥有稳定、高速的镜像来源,极大地提升开发效率和部署的可靠性。

这个方案不仅适用于个人开发者,也适用于小型团队,为他们在国内构建一套可靠的 Docker 生态奠定了基础。希望本文能为你带来实际的帮助,让你能够更加专注于代码本身,享受畅快的 Docker 开发体验!


10. 常见问题 (FAQ)

Q1: 这个方案是完全免费的吗? A1: GitHub Actions 和 Aliyun ACR 都提供免费额度。GitHub Actions 每月有 2000 分钟的 Linux Runner 免费额度。Aliyun ACR 个人版也有一定的免费存储空间和公网下行流量。对于个人项目和小型团队,通常在免费额度内即可满足需求。超出额度或使用高级功能才会产生少量费用。

Q2: 我可以将镜像同步到其他国内 Registry 吗?例如华为云 SWR、腾讯云 TCR? A2: 是的,核心原理是相同的。你只需要修改 config.env 中的 TARGET_REGISTRYTARGET_NAMESPACE,并在 GitHub Secrets 中配置对应 Registry 的用户名和密码(通常也是 AccessKey 或应用密码)。脚本逻辑基本无需改动,因为 Docker CLI 的操作是标准化的。

Q3: 为什么我的 GitHub Actions 仍然无法访问 Docker Hub / 其他海外源? A3: 极少数情况下,GitHub Actions Runner 所在的网络环境也可能临时性遇到问题,或者你尝试同步的源(例如一些私有的或受限的 Registry)本身在国内被严格限制,甚至连海外服务器也无法间接访问。请检查 GitHub Actions 的运行日志,通常会有明确的错误提示。

Q4: 这种镜像同步是否有法律/版权风险? A4: 通常对于公共的、开源的 Docker 镜像,进行同步和分发是允许的。但请务必查阅原始镜像的许可协议,并遵守相关的法律法规。避免同步受限、商业授权或有争议的镜像。对于企业用户,建议咨询法务部门。

Q5: 如果我想强制更新某个镜像,即使它在 ACR 中已经存在了,怎么办? A5: 当前的 sync.sh 脚本会通过 docker manifest inspect 检查目标 ACR 中是否存在相同 tag 的镜像。如果存在,就会跳过。如果你想强制更新,有以下几种方式: 1. 手动从 ACR 中删除旧镜像: 然后再提交 images.txt,脚本就会重新同步。 2. 修改 sync.sh 脚本: 删除 docker manifest inspect 的判重逻辑,或者添加一个参数来控制是否强制更新。但请注意,强制更新会增加流量消耗。 3. 使用不同的 Tag: 如果原始镜像有新内容但保持相同 Tag,可以考虑同步时使用新的 Tag,例如 myimage:latestmyimage:latest-new