简介
本指南演示如何创建一个执行 Docker 构建,然后将 Docker 镜像发布到 Docker Hub 或 GitHub Packages 的工作流。使用单个工作流,您可以将镜像发布到单个注册表或多个注册表。
注意
如果您想推送到另一个第三方 Docker 注册表,“将镜像发布到 GitHub Packages”部分中的示例可以作为良好的模板。
先决条件
我们建议您了解工作流配置选项以及如何创建工作流文件的基本知识。有关更多信息,请参阅“编写工作流”。
您可能还会发现了解以下内容很有帮助:
关于镜像配置
本指南假设您在 GitHub 存储库中存储了 Docker 镜像的完整定义。例如,您的存储库必须包含一个 *Dockerfile*,以及执行 Docker 构建以创建镜像所需的任何其他文件。
您可以使用预定义的注释键添加元数据,包括描述、许可证和源存储库到您的容器镜像。有关更多信息,请参阅“使用容器注册表”。
在本指南中,我们将使用 Docker build-push-action
操作来构建 Docker 镜像并将其推送到一个或多个 Docker 注册表。有关更多信息,请参阅 build-push-action
。
将镜像发布到 Docker Hub
每次在 GitHub 上创建新版本时,您都可以触发一个工作流来发布您的镜像。下面的示例工作流在release
事件被触发且活动类型为published
时运行。
在下面的示例工作流中,我们使用 Docker 的login-action
和build-push-action
操作来构建 Docker 镜像,如果构建成功,则将构建的镜像推送到 Docker Hub。
要推送到 Docker Hub,您需要拥有一个 Docker Hub 帐户,并已创建一个 Docker Hub 存储库。更多信息,请参阅 Docker 文档中的“将 Docker 容器镜像推送到 Docker Hub”。
Docker Hub所需的login-action
选项为:
username
和password
:这是您的 Docker Hub 用户名和密码。我们建议将您的 Docker Hub 用户名和密码存储为密钥,以便它们不会在您的工作流文件中暴露。更多信息,请参阅“在 GitHub Actions 中使用密钥”。
Docker Hub所需的metadata-action
选项为:
images
:您正在构建/推送到 Docker Hub 的 Docker 镜像的命名空间和名称。
Docker Hub所需的build-push-action
选项为:
tags
:您新镜像的标签,格式为DOCKER-HUB-NAMESPACE/DOCKER-HUB-REPOSITORY:VERSION
。您可以设置单个标签(如下所示),也可以在列表中指定多个标签。push
:如果设置为true
,则如果镜像构建成功,它将被推送到注册表。
# This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # GitHub recommends pinning actions to a commit SHA. # To get a newer version, you will need to update the SHA. # You can also reference a tag or branch, but the action may change without warning. name: Publish Docker image on: release: types: [published] jobs: push_to_registry: name: Push Docker image to Docker Hub runs-on: ubuntu-latest permissions: packages: write contents: read attestations: write id-token: write steps: - name: Check out the repo uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: images: my-docker-hub-namespace/my-docker-hub-repository - name: Build and push Docker image id: push uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 with: context: . file: ./Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - name: Generate artifact attestation uses: actions/attest-build-provenance@v1 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
name: Publish Docker image
on:
release:
types: [published]
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
attestations: write
id-token: write
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: my-docker-hub-namespace/my-docker-hub-repository
- name: Build and push Docker image
id: push
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
上述工作流检出 GitHub 存储库,使用login-action
登录注册表,然后使用build-push-action
操作:基于您的存储库的Dockerfile
构建 Docker 镜像;将镜像推送到 Docker Hub,并为镜像应用标签。
在最后一步中,它会为镜像生成工件证明,从而提高供应链安全性。更多信息,请参阅“使用工件证明来确定构建的来源”。
将镜像发布到 GitHub Packages
每次在 GitHub 上创建新版本时,您都可以触发一个工作流来发布您的镜像。下面的示例工作流在将更改推送到release
分支时运行。
在下面的示例工作流中,我们使用 Docker 的login-action
、metadata-action
和build-push-action
操作来构建 Docker 镜像,如果构建成功,则将构建的镜像推送到 GitHub Packages。
GitHub Packages所需的login-action
选项为:
registry
:必须设置为ghcr.io
。username
:您可以使用${{ github.actor }}
上下文来自动使用触发工作流运行的用户帐户名。更多信息,请参阅“访问关于工作流运行的上下文信息”。password
:您可以使用自动生成的GITHUB_TOKEN
密钥作为密码。更多信息,请参阅“自动令牌身份验证”。
GitHub Packages所需的metadata-action
选项为:
images
:您正在构建的 Docker 镜像的命名空间和名称。
GitHub Packages所需的build-push-action
选项为:
context
:将构建的上下文定义为位于指定路径中的一组文件。push
:如果设置为true
,则如果镜像构建成功,它将被推送到注册表。tags
和labels
:这些由metadata-action
的输出填充。
注意
- 此工作流使用未经 GitHub 认证的操作。它们由第三方提供,并受单独的服务条款、隐私政策和支持文档约束。
- GitHub 建议将操作固定到提交 SHA。要获取较新版本,您需要更新 SHA。您也可以引用标签或分支,但操作可能会在未经警告的情况下更改。
# name: Create and publish a Docker image # Configures this workflow to run every time a change is pushed to the branch called `release`. on: push: branches: ['release'] # Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} # There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu. jobs: build-and-push-image: runs-on: ubuntu-latest # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: contents: read packages: write attestations: write id-token: write # steps: - name: Checkout repository uses: actions/checkout@v4 # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. - name: Log in to the Container registry uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. - name: Build and push Docker image id: push uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)." - name: Generate artifact attestation uses: actions/attest-build-provenance@v1 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true
name: Create and publish a Docker image
on:
push:
branches: ['release']
配置此工作流,以便每次将更改推送到名为release
的分支时都运行。
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
为工作流定义两个自定义环境变量。这些用于容器注册表域和此工作流构建的 Docker 镜像的名称。
jobs:
build-and-push-image:
runs-on: ubuntu-latest
此工作流中只有一个作业。它配置为在最新版本的 Ubuntu 上运行。
permissions:
contents: read
packages: write
attestations: write
id-token: write
设置授予此作业中操作的GITHUB_TOKEN
的权限。
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
使用docker/login-action
操作使用将发布包的帐户和密码登录到容器注册表。发布后,包的范围限定为此处定义的帐户。
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
此步骤使用docker/metadata-action提取将应用于指定镜像的标签。id
“meta”允许在后续步骤中引用此步骤的输出。images
值提供标签的基名称。
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
此步骤使用docker/build-push-action
操作基于您的存储库的Dockerfile
构建镜像。如果构建成功,它会将镜像推送到 GitHub Packages。它使用context
参数将构建的上下文定义为位于指定路径中的一组文件。更多信息,请参阅docker/build-push-action
存储库自述文件中的“用法”。它使用tags
和labels
参数使用“meta”步骤的输出来标记镜像。
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
此步骤会为镜像生成工件证明,这是一个关于镜像构建位置和方式的不可伪造的声明。它会提高使用该镜像的人员的供应链安全性。更多信息,请参阅“使用工件证明来确定构建的来源”。
#
name: Create and publish a Docker image
# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
push:
branches: ['release']
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
attestations: write
id-token: write
#
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
上述工作流由对“release”分支的推送触发。它检出 GitHub 存储库,并使用login-action
登录容器注册表。然后,它提取 Docker 镜像的标签。最后,它使用build-push-action
操作来构建镜像并将其发布到容器注册表。
将镜像发布到 Docker Hub 和 GitHub Packages
在一个工作流中,您可以通过为每个注册表使用login-action
和build-push-action
操作来将您的 Docker 镜像发布到多个注册表。
以下示例工作流使用前面部分(“将镜像发布到 Docker Hub”和“将镜像发布到 GitHub Packages”)中的步骤来创建一个将镜像推送到两个注册表的工作流。
# This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # GitHub recommends pinning actions to a commit SHA. # To get a newer version, you will need to update the SHA. # You can also reference a tag or branch, but the action may change without warning. name: Publish Docker image on: release: types: [published] jobs: push_to_registries: name: Push Docker image to multiple registries runs-on: ubuntu-latest permissions: packages: write contents: read attestations: write id-token: write steps: - name: Check out the repo uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the Container registry uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: images: | my-docker-hub-namespace/my-docker-hub-repository ghcr.io/${{ github.repository }} - name: Build and push Docker images id: push uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - name: Generate artifact attestation uses: actions/attest-build-provenance@v1 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
name: Publish Docker image
on:
release:
types: [published]
jobs:
push_to_registries:
name: Push Docker image to multiple registries
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
attestations: write
id-token: write
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: |
my-docker-hub-namespace/my-docker-hub-repository
ghcr.io/${{ github.repository }}
- name: Build and push Docker images
id: push
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
上述工作流检出 GitHub 存储库,使用login-action
两次登录到两个注册表,并使用metadata-action
操作生成标签。然后,build-push-action
操作构建并推送 Docker 镜像到 Docker Hub 和容器注册表。
在最后一步中,它会为镜像生成工件证明,从而提高供应链安全性。更多信息,请参阅“使用工件证明来确定构建的来源”。