Docker 使用 Github Actions 同步镜像到 Aliyun 仓库
创建 Github Actions 配置文件
- 创建并上传该文件到 github 仓库:
.github/workflows/sync-images.yml - 创建 Github 仓库密钥: ALIYUN_USERNAME 和 ALIYUN_PASSWORD
- settings -> Secrets and Variables -> Actions -> New repository secret
- ALIYUN_USERNAME: 阿里云 docker 拉取镜像时的账号
- ALIYUN_PASSWORD: 阿里云 docker 拉取镜像时的密码
yml
name: Sync Images to Aliyun ACR
run-name: Copy ${{ github.event.inputs.source }}/${{ inputs.source_repo }} to ${{ github.event.inputs.destination }}/${{ github.event.inputs.destination_namespace }}/${{ inputs.destination_repo }}
on:
workflow_dispatch:
inputs:
source:
description: '镜像源 (Registry)'
required: true
default: 'docker.io'
destination:
description: '目标源 (Registry)'
required: true
default: 'registry.cn-hangzhou.aliyuncs.com'
destination_namespace:
description: '目标源命名空间 (Namespace)'
required: true
default: 'aday-sync'
source_repo:
description: '仓库及标签 (格式 repo:tag)'
required: true
default: ''
destination_repo:
description: '目标仓库及标签 (格式 repo:tag)'
required: true
default: ''
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Install Skopeo
run: |
sudo apt update
sudo apt install -y skopeo
- name: Sync multi-arch Image to Aliyun ACR
env:
# 源镜像(Docker Hub)
SRC: '${{ github.event.inputs.source }}/${{ github.event.inputs.source_repo }}'
# 目标镜像
DST: '${{ github.event.inputs.destination }}/${{ github.event.inputs.destination_namespace }}/${{ github.event.inputs.destination_repo }}'
run: |
skopeo copy \
--dest-creds "${{ secrets.ALIYUN_USERNAME }}:${{ secrets.ALIYUN_PASSWORD }}" \
--all \
"docker://${SRC}" \
"docker://${DST}"skopeo 同步镜像时可能发生的异常情况:
unknown manifest class for application/vnd.oci.empty.v1+json"错误。unsupported image-specific operation on artifact with type \"application/vnd.docker.attestation.manifest.v1+json\"错误。解决办法:
此时可用 Github Actions 中的 docker/build-push-action 插件重新 rebuild 打包再推送。
参考:Dockerfiles仓库下的 .github/workflows/sync-images-rebuild.yml
同步镜像
进入仓库的 Actions, 页面左侧找到 Sync Images to Aliyun ACR workflow, 点击页面右侧 Run workflow 按钮,填写参数,点击 Run workflow 按钮即可。
- 参数说明:
- 镜像源 (Registry):
docker.io - 目标源 (Registry):
registry.cn-hangzhou.aliyuncs.com - 目标源命名空间 (Namespace):
aday-sync - 仓库及标签 (格式 repo:tag):
debian:12.13 - 目标仓库及标签 (格式 repo:tag):
debian:12.13
- 镜像源 (Registry):
一般只需要填写
源仓库及标签,以及目标仓库及标签即可,其它参数默认即可。aday-sync为默认 Aliyun ACR 命名空间名称。可以根据实际命名空间的名称修改。
注意:
text
1. tag 名称只能包含小写字母、数字、点、中划线、下划线,因此需要将 tag 中的点替换为中划线。
2. 而很多源镜像的 tag 中带有源 namespace 及中划线,在目标 tag 中必须移除不合法的中划线。
3. 建议用下划线 `_` 代替源镜像中的正斜杠 `/`,避免冲突,及达到看见 tag 名称就可以很方便的推测出源镜像的名称。
示例 1:
源镜像:kasmweb/debian-bookworm-desktop:1.18.0
目标镜像:registry.cn-hangzhou.aliyuncs.com/aday-sync/kasmweb_debian-bookworm-desktop:1.18.0
示例 2:
源镜像:jenkins/jenkins:2.558-jdk21
目标镜像:registry.cn-hangzhou.aliyuncs.com/aday-sync/jenkins_jenkins:2.558-jdk21使用 skopeo 检查远程仓库同步镜像的 manifest 列表
shell
# 安装
sudo apt install -y skopeo
# 安装 jq 工具,用来格式化输出 json 和过滤
sudo apt install -y jq
skopeo inspect --raw docker://registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 | jq
# 查看 Digest
skopeo inspect --raw docker://registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 | jq '.Digest'
# 查看 manifests 里的 platform
skopeo inspect --raw docker://registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 | jq '.manifests[].platform'如果无法安装 jq 工具,可以使用 python3(格式化json) + grep(过滤),如下:
shell
# json 格式化输出
skopeo inspect --raw docker://registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 | python3 -m json.tool
# grep 筛选出架构信息。
# -A 3 表示显示匹配行及其后 3 行。'platform' 为筛选关键词。
skopeo inspect --raw docker://registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 | python3 -m json.tool | grep -A 3 'platform'使用 docker 检查本地拉取的镜像的 manifest 列表
shell
docker pull registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13
# 跨平台镜像(运行时要先安装好 QEMU 模拟器)
docker pull --platform linux/arm64/v8 registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13
# 检查本地拉取的镜像的 manifest 列表
docker manifest inspect registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13
# 可以检测拉取下来的镜像的实际架构(检测可能为空,不靠谱)
docker image inspect registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 | grep Architecturedocker_pull.sh 脚本
从 Aliyun 拉取镜像自动 tag 为 docker hub 原始镜像的 tag。
shell
#!/bin/bash
set -euo pipefail
# 检查参数
if [ $# -ne 2 ]; then
echo "输入参数错误!"
echo "=================================================="
echo "用法: $0 <阿里云完整镜像> <本地目标镜像>"
echo "示例: $0 registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 debian:12.13"
echo "=================================================="
exit 1
fi
# 接收两个参数
ALIYUN_IMAGE="$1"
LOCAL_IMAGE="$2"
echo "============================================="
echo "📥 镜像拉取 & 重打标签"
echo "源镜像:$ALIYUN_IMAGE"
echo "目标镜像:$LOCAL_IMAGE"
echo "============================================="
# 1. 拉取阿里云镜像
echo -e "\n[1/3] 拉取镜像..."
docker pull "${ALIYUN_IMAGE}"
# 2. 打成本地标签
echo -e "\n[2/3] 重打标签:${LOCAL_IMAGE}"
docker tag "${ALIYUN_IMAGE}" "${LOCAL_IMAGE}"
# 3. 删除阿里云标签
echo -e "\n[3/3] 删除源镜像标签..."
docker rmi "${ALIYUN_IMAGE}"
echo -e "\n✅ 操作完成!本地镜像:${LOCAL_IMAGE}"
echo ""
# 列出所有以 LOCAL_IMAGE 名称开头的镜像,只显示前 5 行。
echo -e "\n执行命令:docker images | grep -E "^${LOCAL_IMAGE%%:*}" | head -5"
docker images | grep -E "^${LOCAL_IMAGE%%:*}" | head -3脚本执行格式:
shell
docker_pull.sh <Aliyun ACR 仓库镜像> <Docker Hub 镜像(或者也可以修改为自定义镜像标签)>示例:
shell
./docker_pull.sh registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 debian:12.13添加到环境变量可读取的位置
shell
# 放到环境变量的位置,并且去掉 .sh 后缀
sudo mv docker_pull.sh /usr/local/bin/docker_pull
# 设置可执行权限
sudo chmod +x /usr/local/bin/docker_pull为什么要去掉 docker_pull.sh 的 .sh 后缀? 携带 .sh 后缀的脚本执行时也要带 .sh 后缀; 而我们希望执行时直接
docker_pull <阿里云完整镜像> <本地目标镜像>,而不是docker_pull.sh <阿里云完整镜像> <本地目标镜像>。
任意目录直接执行
shell
docker_pull registry.cn-hangzhou.aliyuncs.com/aday-sync/debian:12.13 debian:12.13