使用 GitHub Actions 将 DockerHub、gcr.io、k8s.io、ghcr.io 等国外镜像转存到阿里云个人版 ACR,方便国内服务器拉取。
- 支持任意公开 Docker 镜像仓库。
- 支持最大 40GB 的大型镜像。
- 支持
--platform指定镜像架构。 - 支持网页管理
images.txt,并查看阿里云 ACR 仓库和 Tag 状态。
原项目视频教程:https://www.bilibili.com/video/BV1Zn4y19743/
原作者:技术爬爬虾
B 站、抖音、Youtube 全网同名,转载请注明作者。
images.txt:要同步的镜像列表。scheduled-images.txt:只保存需要定时重新 pull 的镜像。.github/workflows/docker.yaml:按触发类型读取普通或定时镜像列表,拉取源镜像并推送到阿里云 ACR。AcrMirrorManager/:内置的 .NET 9 Razor Pages 管理页面。doc/:使用说明图片和管理页面截图。
- 在
images.txt手动添加镜像,或在 ACR Mirror Manager 页面提交镜像。 images.txt变更后,GitHub Actions 自动运行;到达定时时间时则只读取scheduled-images.txt。- workflow 拉取源镜像,按规则生成阿里云 ACR 仓库名。
- workflow 将镜像推送到阿里云 ACR。
- 管理页面通过 Registry V2 API 检查仓库和 Tag 是否已经存在。
为了避免修改管理页面代码时也触发镜像同步,workflow 的 push 触发已经限制为只监听 images.txt。
登录阿里云容器镜像服务:
https://cr.console.aliyun.com/
启用个人实例,创建一个命名空间,也就是后面要用的 ALIYUN_NAME_SPACE。
进入访问凭证页面,获取下面三个值:
ALIYUN_REGISTRY_USER:用户名。ALIYUN_REGISTRY_PASSWORD:密码。ALIYUN_REGISTRY:仓库地址。
Fork 本仓库后,进入自己的仓库,点击 Actions,启用 GitHub Actions 功能。
进入 Settings -> Secrets and variables -> Actions -> New repository secret,添加下面四个 Secret:
ALIYUN_NAME_SPACEALIYUN_REGISTRY_USERALIYUN_REGISTRY_PASSWORDALIYUN_REGISTRY
可以直接编辑根目录 images.txt:
- 可以写 tag,不写 tag 时默认使用
latest。 - 可以用
--platform=linux/arm64或--platform linux/arm64指定架构。 - 可以用
k8s.gcr.io/kube-state-metrics/kube-state-metrics这种格式指定私有路径。 - 可以用
#注释暂时不处理的镜像。
示例:
nginx
docker.io/library/node:20-bookworm-slim
--platform=linux/arm64 xiaoyaliu/alist
# ghcr.io/home-assistant/home-assistant:stable
提交 images.txt 后,GitHub Actions 会自动同步镜像。
回到阿里云容器镜像服务,进入镜像仓库,点击任意镜像可以查看镜像状态。仓库可以改成公开,公开后拉取镜像不需要登录。
国内服务器拉取示例:
docker pull registry.cn-hangzhou.aliyuncs.com/shrimp-images/alpine其中:
registry.cn-hangzhou.aliyuncs.com是ALIYUN_REGISTRY。shrimp-images是ALIYUN_NAME_SPACE。alpine是同步后的仓库名。
ACR Mirror Manager 是内置的网页管理页面,代码在 AcrMirrorManager/。它本身不拉取镜像、不推送镜像,也不依赖本机 Docker daemon;页面只负责更新当前 GitHub 仓库根目录的 images.txt,真正同步仍由 GitHub Actions 完成。
主要功能:
- 在网页提交一个或多个源镜像,自动写入
images.txt。 - 支持“只处理本次镜像”:提交时把其它未注释镜像加
#。 - 支持重 pull 已有镜像,让 GitHub Actions 重新处理选中的源镜像。
- 支持把指定镜像加入或移出 GitHub Actions 定时重新 pull 列表。
- 支持从
images.txt移除源镜像,并同步更新本地缓存。 - 通过 Docker Registry HTTP API V2 查询阿里云 ACR 仓库和 Tag。
- 展示镜像状态、Tag、Digest、源镜像地址和目标镜像地址。
- 使用本地缓存记录仓库、Tag、Action 追踪和待刷新任务。
进入管理页面目录,复制配置模板:
cd AcrMirrorManager
cp .env.example .env部署原仓库时只需要改下面这些字段:
RegistryV2__Registry=registry.cn-shanghai.aliyuncs.com
RegistryV2__Namespace=你的阿里云命名空间
RegistryV2__Username=你的阿里云镜像仓库登录用户名
RegistryV2__Password=你的阿里云镜像仓库登录密码
GitHubMirror__Token=github_pat_xxx如果部署的是 fork 仓库,再把 GitHubMirror__RepositoryUrl 改成自己的 fork 地址:
GitHubMirror__RepositoryUrl=https://github.com/你的账号/docker_image_pusher这个配置仍然需要存在,因为管理页面要通过 GitHub API 读写这个仓库的 images.txt。它现在指向的是合并后的同一个仓库,不再是另一个配套项目。
GitHubMirror__Token 用于读写 images.txt 和 scheduled-images.txt。如果使用 GitHub fine-grained token,建议授予:
- Repository access:当前
docker_image_pusher仓库,或你 fork 后的仓库。 - Contents:Read and write。
- Actions:Read。
默认不需要 Actions 写权限,因为 images.txt 变更会自动触发 workflow。
在 AcrMirrorManager/ 目录启动:
docker-compose up -d --build默认访问地址:
http://localhost:15187
常用命令:
docker-compose logs -f
docker-compose down
docker-compose down -v可以在 .env 里修改宿主机端口:
APP_HTTP_PORT=15187Dockerfile 默认使用微软官方 .NET 镜像,也可以用私有基础镜像覆盖:
SDK_IMAGE=mcr.microsoft.com/dotnet/sdk:9.0
ASPNET_IMAGE=mcr.microsoft.com/dotnet/aspnet:9.0cd AcrMirrorManager
dotnet run --project AcrMirrorManager.csproj本地 dotnet run 不会自动读取 Docker 用的 .env。可以先导入当前 shell:
set -a
source .env
set +a
dotnet run --project AcrMirrorManager.csproj也可以使用 dotnet user-secrets:
dotnet user-secrets set "RegistryBackend:Mode" "RegistryV2" --project AcrMirrorManager.csproj
dotnet user-secrets set "RegistryV2:Registry" "registry.cn-shanghai.aliyuncs.com" --project AcrMirrorManager.csproj
dotnet user-secrets set "RegistryV2:Namespace" "你的阿里云命名空间" --project AcrMirrorManager.csproj
dotnet user-secrets set "RegistryV2:Username" "你的阿里云镜像仓库登录用户名" --project AcrMirrorManager.csproj
dotnet user-secrets set "RegistryV2:Password" "你的阿里云镜像仓库登录密码" --project AcrMirrorManager.csproj
dotnet user-secrets set "GitHubMirror:RepositoryUrl" "https://github.com/你的账号/docker_image_pusher" --project AcrMirrorManager.csproj
dotnet user-secrets set "GitHubMirror:Token" "github_pat_xxx" --project AcrMirrorManager.csproj仓库根目录包含 .gitlab-ci.yml,这是个人 Windows 本地 runner 部署示例。GitLab 默认只识别仓库根目录的 .gitlab-ci.yml,所以它不能放在 AcrMirrorManager/ 子目录。
当前 CI 约定:
- runner tag:
local_168 - 只部署
main分支 - 部署目录:
D:\stocks\docker_image_pusher - 首次运行时目录不存在会自动 clone 整个仓库
- 后续运行会 fetch 并 reset 到当前 CI commit
- 进入
AcrMirrorManager子目录后执行docker-compose up -d --build
推荐在 GitLab CI/CD Variables 里新增一个 File 类型变量:
Key: ACR_MIRROR_ENV_FILE
Type: File
Value: 完整 .env 文件内容
CI 会把这个文件复制到:
D:\stocks\docker_image_pusher\AcrMirrorManager\.env
如果不配置 ACR_MIRROR_ENV_FILE,也可以手动在部署机维护这个 .env 文件。
workflow 和管理页面使用同一套命名规则:
- 去掉 registry host,例如
docker.io/library/node:20->library_node。 - 去掉 tag,只把 tag 用于最终目标镜像地址。
- 路径中的
/替换为_。 - 如果包含
--platform=linux/arm64或--platform linux/arm64,仓库名追加_linux_arm64。
示例:
docker.io/library/node:20-bookworm-slim -> library_node:20-bookworm-slim
ghcr.io/immich-app/immich-server:release -> immich-app_immich-server:release
--platform=linux/arm64 xiaoyaliu/alist -> xiaoyaliu_alist_linux_arm64:latest
多架构镜像需要在 images.txt 中手动指定架构。
如果不同命名空间下存在同名镜像,会把命名空间作为前缀加到镜像名称中。
xhofe/alist
xiaoyaliu/alist
定时重新 pull 由 GitHub Actions 执行,不依赖 ACR Mirror Manager 容器一直在线。
使用方式:
- 打开管理页面,在镜像所在行点击“加入定时”;也可以先勾选多个镜像,再点击“选中加入定时”。
- 页面把该源镜像写入根目录的
scheduled-images.txt。 - GitHub Actions 到达定时时间后只处理这个文件中的镜像,不会重新 pull
images.txt中的全部镜像。 - 点击“取消定时”,或从管理页面移除镜像,会同时把它移出定时列表。
当前 .github/workflows/docker.yaml 默认每天 23:00 UTC 执行,也就是北京时间次日 07:00 左右。要修改频率,只需调整 workflow 中的 cron:
schedule:
- cron: '0 23 * * *'cron 使用 UTC 时区。修改 scheduled-images.txt 本身不会立即触发同步;手动“重 pull”仍走 images.txt 的即时 push 触发。定时列表为空时,workflow 会跳过 Docker 初始化和镜像处理。
- 缓存文件默认在
AcrMirrorManager/App_Data/registry-v2-cache.json。 - Docker 部署时该路径挂载到
acrmirror-datavolume。 - 页面普通打开优先读缓存,避免每次都请求远端 Registry。
- 如果缓存为空,页面会自动读取 GitHub
images.txt,反推仓库列表并探测 Registry V2。 - 顶部刷新按钮会强制重新探测。
- 后台任务每分钟检查待刷新任务。
RegistryV2:DailyMissingRefreshHour控制每天几点刷新未推送仓库。RegistryV2:PostSubmitRefreshMinutes控制提交新镜像后延迟探测的分钟列表,默认[3, 5, 10, 20]。
- 不要提交真实 token、密码、AK/SK。
AcrMirrorManager/.env已被忽略,不应提交。AcrMirrorManager/Dockerfile不复制.env,不会把密钥写进镜像层。- 管理页面可以更新 GitHub 仓库并查看 ACR 状态,建议只部署在可信网络内,或放在登录、IP 白名单、Cloudflare Access、Tailscale、反向代理 Basic Auth 后面。








