1. 简介

私有 Docker 镜像在访问受限仓库或注册中心中存储的镜像时需要用户进行身份验证。与任何人都可以访问的公有镜像不同,这些镜像仅对具有正确凭证(如用户名和密码、令牌或 API 密钥)的用户开放访问权限。

因此,在 GitHub Actions 工作流中使用私有 Docker 镜像时,必须在工作流中配置身份验证。本教程将介绍在 GitHub Actions 工作流中安全访问私有 Docker 注册中心的关键技术。所有命令均在 Ubuntu 20.04 上使用 Docker Engine 28.1.1 执行。


2. 前提条件

在 GitHub Actions 中实现私有 Docker 镜像访问之前,我们需要准备以下内容:

  1. 已启用 Actions 的 GitHub 仓库
  2. 可访问的私有 Docker 注册中心(本文使用 Docker Hub、GitHub Container Registry、AWS Elastic Container Registry 和 Google Artifact Registry)
  3. 具有适当权限的注册中心凭证
  4. 对 GitHub Actions 工作流语法有基本了解

接下来,我们创建一个示例镜像用于后续演示。定义一个使用 Alpine 基础镜像的 Dockerfile,运行时输出 Hello from Baeldung!

$ cat Dockerfile
FROM alpine:latest
CMD ["echo", "Hello from Baeldung!"]

构建镜像并命名为 hello-baeldung:1.0

$ docker build -f Dockerfile -t hello-baeldung:1.0 .

设置环境变量方便后续使用:

$ IMAGE=hello-baeldung
$ TAG=1.0
$ LOCAL_IMAGE=$IMAGE:$TAG

运行本地镜像确认输出:

$ docker run hello-baeldung:1.0 
Hello from Baeldung!

输出如预期所示。


3. 使用 GitHub Container Registry (GHCR)

GitHub Container Registry(GHCR)是 GitHub 提供的托管 Docker 镜像注册服务,允许在 GitHub 生态系统中无缝存储、管理和分发 Docker 镜像。

GHCR 的镜像地址格式如下:

ghcr.io/USERNAME/IMAGE:TAG
ghcr.io/ORGANIZATION/IMAGE:TAG

3.1. 生成个人访问令牌(PAT)

要将镜像推送到 GHCR,需使用 GitHub 个人访问令牌(PAT)进行身份验证。

前往 GitHub 仪表盘,创建一个具有 write:packagesdelete:packages 权限的 PAT:

GitHub PAT 创建界面

将令牌保存为环境变量并登录 GHCR:

$ GHCR_PAT=<personal_access_token>
$ echo "$GHCR_PAT" | docker login ghcr.io -u <GITHUB_USERNAME> --password-stdin

3.2. 推送镜像

设置 GHCR 仓库地址并推送镜像:

$ GHCR_REPO=ghcr.io/$GHCR_USER/$IMAGE
$ docker tag $LOCAL_IMAGE $GHCR_REPO:$TAG
$ docker push $GHCR_REPO:$TAG

镜像将被安全地存储在 GHCR 中。

3.3. 在 GitHub Actions 中使用私有 GHCR 镜像

创建工作流文件 .github/workflows/ghcr-private-images.yaml

on:
  push:
    branches:
      - main

jobs:
  run-ghcr-image:
    runs-on: ubuntu-latest
    steps:
      - name: Login to GitHub Container Registry
        run: echo "${{ secrets.TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

      - name: Pull and Run Image
        run: |
            docker pull ghcr.io/${{ secrets.OWNER }}/${{ secrets.IMAGE }}:${{ secrets.TAG }}
            docker run ghcr.io/${{ secrets.OWNER }}/${{ secrets.IMAGE }}:${{ secrets.TAG }}

在 GitHub 仓库中配置以下 secrets:

  • TOKEN: GitHub PAT
  • OWNER: 用户名或组织名
  • IMAGE: 镜像名(如 hello-baeldung
  • TAG: 镜像标签(如 1.0

提交工作流后,在 Actions 页面查看执行结果:

GitHub Actions 执行结果

✅ 输出为 Hello from Baeldung!,说明镜像拉取和运行成功。


4. 使用 Docker Hub

Docker Hub 是 Docker 提供的官方镜像注册服务,用于共享和存储容器镜像。

4.1. 创建 PAT

在 Docker Hub 仪表盘创建一个具有读写权限的 PAT:

Docker Hub PAT 创建界面

保存凭证并登录:

$ DOCKERHUB_TOKEN=<dockerhub_pat_token>
$ DOCKERHUB_USER=<dockerhub_username>
$ echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USER" --password-stdin

4.2. 推送镜像

设置仓库地址并推送:

$ DOCKERHUB_REPO=$DOCKERHUB_USER/$IMAGE
$ docker tag $LOCAL_IMAGE $DOCKERHUB_REPO:$TAG
$ docker push $DOCKERHUB_REPO:$TAG

将仓库设为私有:

Docker Hub 私有仓库设置

4.3. 在 GitHub Actions 中使用私有 Docker Hub 镜像

创建工作流文件 .github/workflows/dockerhub-private-image.yaml

name: Run Private DockerHub Image

on:
  push:
    branches:
    - main

jobs:
  run-dockerhub-image:
    runs-on: ubuntu-latest
    steps:
      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Pull and Run Image
        run: |
          docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.IMAGE }}:${{ secrets.TAG }}
          docker run ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.IMAGE }}:${{ secrets.TAG }}

在 GitHub 设置以下 secrets:

  • DOCKERHUB_USERNAME
  • DOCKERHUB_TOKEN

提交后查看执行结果:

Docker Hub 执行结果

✅ 成功输出 Hello from Baeldung!


5. 使用 AWS Elastic Container Registry (ECR)

AWS ECR 是 Amazon 提供的托管 Docker 注册中心,支持安全存储和管理 Docker 镜像。

5.1. 账号配置

设置 AWS 区域和账户 ID:

$ AWS_REGION=<aws_region>
$ AWS_ACCOUNT_ID=<account_id>

登录 ECR:

$ aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com

5.2. 推送镜像

创建仓库并推送:

$ aws ecr describe-repositories --repository-names "$IMAGE" --region $AWS_REGION >/dev/null 2>&1 || \
aws ecr create-repository --repository-name "$IMAGE" --region $AWS_REGION

$ ECR_REPO=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE
$ docker tag $LOCAL_IMAGE $ECR_REPO:$TAG
$ docker push $ECR_REPO:$TAG

5.3. 创建 IAM 用户

创建 IAM 用户并为其分配访问 ECR 的权限:

$ aws iam create-user --user-name github-ecr-user
$ aws iam create-access-key --user-name github-ecr-user

创建并绑定策略:

$ aws iam create-policy --policy-name ECRReadOnlyAccess --policy-document file://ecr-policy.json
$ aws iam attach-user-policy --user-name github-ecr-user --policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/ECRReadOnlyAccess

5.4. 在 GitHub Actions 中使用私有 ECR 镜像

创建工作流文件 .github/workflows/aws-ecr-private-images.yaml

name: Run Private AWS ECR Image

on:
  push:
    branches:
    - main

jobs:
  run-ecr-image:
    runs-on: ubuntu-latest
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Pull and Run Image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
          IMAGE_TAG: ${{ secrets.TAG }}
        run: |
          docker pull $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          docker run $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

在 GitHub 设置以下 secrets:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_REGION
  • ECR_REPOSITORY

提交后查看执行结果:

ECR 执行结果

✅ 成功输出 Hello from Baeldung!


6. 使用 Google Artifact Registry

Google Artifact Registry 是 Google Cloud 提供的包管理与容器镜像注册服务。

6.1. 项目配置与认证

配置 Docker 与 gcloud:

$ gcloud auth configure-docker

6.2. 推送镜像

设置项目 ID 和仓库地址:

$ PROJECT_ID=$(gcloud config get-value project)
$ GCR_REPO=gcr.io/$PROJECT_ID/$IMAGE
$ docker tag $LOCAL_IMAGE $GCR_REPO:$TAG
$ docker push $GCR_REPO:$TAG

6.3. 创建服务账号密钥

创建服务账号并授权:

$ gcloud iam service-accounts create github-gcr-user
$ gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:github-gcr-user@$PROJECT_ID.iam.gserviceaccount.com" --role="roles/storage.objectViewer"
$ gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:github-gcr-user@$PROJECT_ID.iam.gserviceaccount.com" --role="roles/artifactregistry.reader"

生成密钥并编码:

$ gcloud iam service-accounts keys create key.json --iam-account=github-gcr-user@$PROJECT_ID.iam.gserviceaccount.com
$ base64 -w 0 key.json > key.b64

6.4. 在 GitHub Actions 中使用私有 GCR 镜像

创建工作流文件 .github/workflows/gcr-private-image.yaml

name: Run Private GCR Image

on:
  push:
    branches:
    - main

jobs:
  run-gcr-image:
    runs-on: ubuntu-latest
    steps:
      - id: 'auth'
        uses: 'google-github-actions/auth@v1'
        with:
            credentials_json: '${{ secrets.GCP_CREDENTIALS }}'
    
      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v1

      - name: Configure Docker for GCR
        run: |
          gcloud auth configure-docker

      - name: Pull and Run Image
        env:
          GCR_REGISTRY: gcr.io
          GCP_PROJECT: ${{ secrets.GCP_PROJECT_ID }}
          IMAGE_NAME: ${{ secrets.IMAGE }}
          IMAGE_TAG: ${{ secrets.TAG }}
        run: |
          docker pull $GCR_REGISTRY/$GCP_PROJECT/$IMAGE_NAME:$IMAGE_TAG
          docker run $GCR_REGISTRY/$GCP_PROJECT/$IMAGE_NAME:$IMAGE_TAG

在 GitHub 设置以下 secrets:

  • GCP_PROJECT_ID
  • GCP_CREDENTIALS(base64 编码的密钥)

提交后查看执行结果:

GCR 执行结果

✅ 成功输出 Hello from Baeldung!


7. 总结

本文介绍了如何在 GitHub Actions 中安全地使用来自以下注册中心的私有 Docker 镜像:

  • GitHub Container Registry
  • Docker Hub
  • AWS Elastic Container Registry
  • Google Artifact Registry

我们通过使用 IAM、服务账号、PAT 和仓库 secrets 实现了安全认证,确保了工作流的安全性和可维护性。这些方法是目前 CI/CD 中推荐的最佳实践。


原始标题:Use Private Docker Image in GitHub Actions