
GitHub PackagesのコンテナレジストリにGitHub ActionsからイメージをPUSHしてみた
GitHub には GitHub Packages というサービスがあり、コンテナイメージを含むさまざまなソフトウェアパッケージをホストできます。
本記事では、GitHub Actions経由で GitHub Packagesのコンテナレジストリ(Container registry)にイメージをPUSHする方法を紹介します。
GitHub Packages の Container registry について
GitHub Packages は、コンテナイメージを含むさまざまなソフトウェアパッケージをホストするサービスです。
Container registryはコンテナイメージをホストするサービスで、古くから提供されていたDocker registry(docker.pkg.github.com)を置き換えるものです。
ストレージと転送量に応じて課金され、プランに応じた一定の無料枠があります。
特に、パブリックなパッケージは無料で利用でき(明確なrate limitはない模様)、GitHub ActionsからイメージをPULLする場合は転送コストがかからない点は特筆に値します。
利用費の詳細は、次のドキュメントを参照してください
GitHub ActionsからGitHub Container registryにイメージPUSHしてみた
GitHub ActionsからGitHub Container registryにイメージPUSHするうえで、大事な点は以下のとおりです。
- 基本的には、PUSH先レジストリのホストをGitHub Container registryのホスト(
ghcr.io
)に向けるだけ - registry との認証では、自動的に払い出される
GITHUB_TOKEN
を利用 - GitHub Actions呼び出し元ではないプライベートレポジトリのイメージをPULLする場合は、Personal Access Token(PAT)が必要
ドキュメントやワークフローのウィザード通りにやれば、PUSHできます。
次のワークフローは Actions → New Workflow → Publish Docker Container で生成されるワークフローを簡素化したものです。
レポジトリの .github/workflows/container-publish.yml
等に設置してください。
name: Create and publish a container image
on:
push:
branches: [ "main" ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
アカウント・レポジトリや認証情報は変数で渡しているため、コピペで他のレポジトリにも転用しやすいようにしています。
全体で数十行と短いですが、大事なポイントは以下です
- PUSH先のGitHubコンテナレジストリは、環境変数
REGISTRY
で指定 - レポジトリのアカウント・レポジトリ情報は
${{ github.repository }}
で取得 - レジストリとの認証は Log into registry のステップで実施しています。変数のみ
補足:公式ドキュメントのワークフローサンプル
最後に、公式ドキュメントにある GitHub AcitionsからのPUSH方法も共有します。
OCIラベル(メタデータ)を付与するなど、より実環境向けの丁寧な実装です。
#
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 [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds).
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true