如何通过GitHub Actions将GHCR指定Commit SHA的镜像复制到ACR并迁移所有标签与元数据
GitHub Actions 同步 GHCR 镜像到 ACR(含全标签+元数据)
解决思路
你之前用Docker拉取推送的方式拿不到对应SHA的所有标签,核心问题是Docker本身没法直接查询镜像SHA关联的标签列表。这里用GitHub Packages API查标签,搭配skopeo工具(比Docker更适合跨注册表同步,还能完整保留元数据)来搞定,不用本地拉取镜像,效率更高。
完整工作流代码
name: Sync GHCR to ACR on: workflow_dispatch: inputs: commit_sha: description: '要同步的镜像对应的Commit SHA(完整SHA-256)' required: true ghcr_image: description: 'GHCR镜像全名(比如 ghcr.io/your-account/your-app)' required: true acr_registry: description: 'ACR注册表地址(比如 youracr.azurecr.io)' required: true acr_repo: description: 'ACR里的目标镜像路径(比如 your-account/your-app)' required: true jobs: sync: runs-on: ubuntu-latest steps: - name: 安装 skopeo run: | sudo apt update && sudo apt install -y skopeo - name: 登录GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: 登录ACR uses: azure/docker-login@v1 with: login-server: ${{ inputs.acr_registry }} username: ${{ secrets.ACR_USERNAME }} password: ${{ secrets.ACR_PASSWORD }} - name: 查GHCR中对应SHA的所有标签 id: fetch_tags run: | # 调用GitHub Packages API筛选出关联该SHA的标签 TAGS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/users/${{ github.repository_owner }}/packages/container/${{ inputs.ghcr_image }}/versions" | \ jq -r --arg SHA "${{ inputs.commit_sha }}" '.[] | select(.metadata.container.config.Digest | contains($SHA)) | .name') echo "tags=$TAGS" >> $GITHUB_OUTPUT - name: 同步镜像+所有标签到ACR run: | SOURCE="${{ inputs.ghcr_image }}@sha256:${{ inputs.commit_sha }}" # 先同步带SHA的基础镜像 skopeo copy --all docker://$SOURCE docker://${{ inputs.acr_registry }}/${{ inputs.acr_repo }}@sha256:${{ inputs.commit_sha }} # 给ACR镜像逐个添加标签 for TAG in ${{ steps.fetch_tags.outputs.tags }}; do skopeo copy docker://$SOURCE docker://${{ inputs.acr_registry }}/${{ inputs.acr_repo }}:$TAG done
关键细节说明
为什么用skopeo?
它直接在注册表之间复制镜像,不用拉到本地,还能完整保留镜像的元数据(环境变量、入口点、LABEL等),比docker pull/push省心多了。怎么拿到对应SHA的标签?
通过GitHub的Packages API遍历镜像的所有版本,筛选出元数据里Digest包含目标Commit SHA的条目,提取这些条目的标签名。注意输入的SHA得是完整的SHA-256值,不然匹配可能出问题。权限配置
- GHCR登录:用默认的
GITHUB_TOKEN就行,只要工作流有packages:read权限(默认已开启)。 - ACR登录:得在GitHub仓库的Secrets里存好
ACR_USERNAME(ACR的管理员账号或服务主体用户名)和ACR_PASSWORD(对应密码/密钥)。
- GHCR登录:用默认的
注意点
- 如果你的镜像是多架构的(比如amd64+arm64),
--all参数会同步所有架构的镜像层,别漏加。 - 要是标签列表为空,说明输入的SHA没有匹配到任何GHCR镜像,得检查SHA或者镜像名是否正确。
- 可以给循环加个判断,比如
if [ -n "$TAG" ]; then ...; fi,避免空标签导致错误。
内容的提问来源于stack exchange,提问作者Zefferno
相关产品推荐
相关产品推荐

