GitHub PackagesのコンテナレジストリにGitHub ActionsからイメージをPUSHしてみた

GitHub PackagesのコンテナレジストリにGitHub ActionsからイメージをPUSHしてみた

Clock Icon2025.02.25

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する場合は転送コストがかからない点は特筆に値します。

利用費の詳細は、次のドキュメントを参照してください

https://docs.github.com/billing/managing-billing-for-your-products/managing-billing-for-github-packages/about-billing-for-github-packages

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-actions-ghcr-workflow

レポジトリの .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

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.