# Docker イメージの発行

このチュートリアルでは、継続的インテグレーション (CI) ワークフローの一部として、Docker Hubや GitHub Packages などのレジストリに Docker イメージを発行する方法について説明します。

## はじめに

このガイドでは、Docker ビルドを実行し、Docker イメージを Docker Hub または GitHub Packages に発行するワークフローを作成する方法について説明します。 1つのワークフローで、1つのレジストリあるいは複数のレジストリにイメージを公開できます。

> \[!NOTE]
> 別のサードパーティの Docker レジストリにプッシュする場合は、「[イメージをGitHub Packagesに発行する](#publishing-images-to-github-packages)」セクションの例を適切なテンプレートとして使用できます。

## 前提条件

ワークフローの設定オプションと、ワークフローファイルの作成方法についての基本的な知識を持っておくことを推奨しています。 詳しくは、「[ワークフローの書き込み](/ja/enterprise-server@3.22/actions/how-tos/write-workflows)」をご覧ください。

以下についての基本的な理解があると役に立つでしょう。

* [GitHub Actions でのシークレットの使用](/ja/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets)
* [ワークフローでの認証に GITHUB\_TOKEN を使用する](/ja/enterprise-server@3.22/actions/tutorials/authenticate-with-github_token)
* [Dockerレジストリの利用](/ja/enterprise-server@3.22/packages/working-with-a-github-packages-registry/working-with-the-docker-registry)

## イメージの設定について

このガイドでは、 GitHub リポジトリに格納されている Docker イメージの完全な定義があることを前提としています。 たとえば、リポジトリにはイメージを作成するための Docker の構築を行うのに必要な *Dockerfile* やその他のファイルが含まれていなければなりません。

定義済みの注釈キーを使って、説明、ライセンス、ソース リポジトリなどのメタデータをコンテナー イメージに追加できます。 詳細については、 [AUTOTITLE を](/ja/enterprise-server@3.22/packages/working-with-a-github-packages-registry/working-with-the-container-registry#labelling-container-images)参照してください。

このガイドでは、Docker `build-push-action` アクションを使用して Docker イメージを構築し、1 つまたは複数の Docker レジストリにプッシュします。 詳細については、「[`build-push-action`](https://github.com/marketplace/actions/build-and-push-docker-images)」を参照してください。

> \[!NOTE]
> GitHub ActionsGitHub Enterprise Serverでは、GitHub.comまたはGitHub Marketplaceに対するアクションへのアクセスが制限される場合があります。 詳細については、「 [AUTOTITLE」](/ja/enterprise-server@3.22/admin/managing-github-actions-for-your-enterprise/managing-access-to-actions-from-githubcom) を参照し、 GitHub Enterprise サイト管理者にお問い合わせください。

## Docker Hubへのイメージの発行

> \[!NOTE]
> 通常、Docker Hub により、プッシュ操作とプル操作の両方にレート制限が課せられます。これは、セルフホステッド ランナーのジョブに影響します。 ただし、GitHub と Docker の間の同意に基づくこれらの制限は、GitHub ホステッド ランナーには適用されません。

GitHubで新しいリリースを作成するたびに、ワークフローをトリガーしてイメージを発行できます。 次の例のワークフローは、`release` イベントが `published` アクティビティの種類でトリガーされたときに実行されます。

次のワークフロー例では、Docker `login-action` アクションと `build-push-action` アクションを使用して Docker イメージをビルドし、ビルドが成功した場合はビルドされたイメージをDocker Hubにプッシュします。

Docker Hubにプッシュするには、Docker Hub アカウントを用意し、Docker Hub リポジトリを作成する必要があります。 詳細については、Docker ドキュメントの「[ Docker コンテナー イメージをDocker Hub](https://docs.docker.com/docker-hub/quickstart/#step-3-build-and-push-an-image-to-docker-hub)に適用する」を参照してください。

Docker Hubに必要な `login-action` オプションは次のとおりです。

* `username` と `password`: これはDocker Hubのユーザー名とパスワードです。 Docker Hubユーザー名とパスワードをシークレットとして保存して、ワークフロー ファイルに公開しないようにすることをお勧めします。 詳しくは、「[GitHub Actions でのシークレットの使用](/ja/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets)」をご覧ください。

Docker Hubに必要な `metadata-action` オプションは次のとおりです。

* `images`: Docker Hub にビルドまたはプッシュする Docker イメージの名前空間と名前。

Docker Hubに必要な `build-push-action` オプションは次のとおりです。

* `tags`: `DOCKER-HUB-NAMESPACE/DOCKER-HUB-REPOSITORY:VERSION` 形式の新しいイメージのタグ。 以下のとおり、単一のタグを設定することも、リストに複数のタグを指定することもできます。
* `push`: `true` に設定した場合は、イメージが正常に構築されると、レジストリにプッシュされます。

```yaml copy
# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

name: Publish Docker image

on:
  release:
    types: [published]

jobs:
  push_to_registry:
    name: Push Docker image to Docker Hub
    runs-on: [self-hosted]
    permissions:
      packages: write
      contents: read
      
      
    steps:
      - name: Check out the repo
        uses: actions/checkout@v6

      - 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 }}

```

上記のワークフローでは、GitHub リポジトリをチェックアウトし、`login-action` を使用してレジストリにログインした後、`build-push-action` アクションを使用して、リポジトリの `Dockerfile` に基づいて Docker イメージを構築します。イメージをDocker Hubにプッシュし、画像にタグを適用します。

## イメージを公開 GitHub Packages

> \[!NOTE] 現在、Container registry は パブリック プレビュー に対して GitHub Enterprise Server 段階であり、変更される可能性があります。

GitHub Packages を使うには、Container registry と Subdomain Isolation の両方を有効にする必要があります。 詳しくは、「[コンテナレジストリの利用](/ja/enterprise-server@3.22/packages/working-with-a-github-packages-registry/working-with-the-container-registry)」をご覧ください。

GitHubで新しいリリースを作成するたびに、ワークフローをトリガーしてイメージを発行できます。 次の例のワークフローは、変更が `release` ブランチにプッシュされたときに実行されます。　

次のワークフロー例では、Docker `login-action` 、 `build-push-action` アクションを使用して Docker イメージをビルドし、ビルドが成功した場合は、ビルドされたイメージを GitHub Packagesにプッシュします。

`login-action`に必要なGitHub Packagesオプションは次のとおりです。

* `registry`: `containers.HOSTNAME`に設定する必要があります。
* `username`: `${{ github.actor }}` コンテキストを使用して、ワークフローの実行をトリガーしたユーザーのユーザー名を自動的に使用できます。 詳しくは、「[コンテキスト リファレンス](/ja/enterprise-server@3.22/actions/reference/workflows-and-actions/contexts#github-context)」をご覧ください。
* `password`: 自動的に生成された `GITHUB_TOKEN` シークレットをパスワードに使用できます。 詳しくは、「[ワークフローでの認証に GITHUB\_TOKEN を使用する](/ja/enterprise-server@3.22/actions/tutorials/authenticate-with-github_token)」をご覧ください。

`build-push-action`に必要なGitHub Packagesオプションは次のとおりです。

* `push`: `true`に設定すると、イメージが正常にビルドされるとレジストリにプッシュされます。
* `tags`: `containers.HOSTNAME/OWNER/REPOSITORY/IMAGE_NAME:VERSION` 形式で設定する必要があります。

  たとえば、`octo-image`のGitHub Enterprise Serverに保存`https://HOSTNAME/octo-org/octo-repo`という名前のイメージの場合、`tags` オプションを `containers.HOSTNAME/octo-org/octo-repo/octo-image:latest` に設定する必要があります。 以下に示すように 1 つのタグを設定することも、リストに複数のタグを指定することもできます。

> \[!NOTE]
>
> * このワークフローでは、GitHub によって認定されていないアクションが使われます。 それらはサード パーティによって提供され、個別のサービス使用条件、プライバシー ポリシー、およびサポート ドキュメントが適用されます。
> * GitHub では、コミット SHA にアクションをピン留めすることをお勧めします。 新しいバージョンを取得するには、SHA を更新する必要があります。 タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

```yaml annotate copy
#
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: containers.HOSTNAME
  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: [self-hosted]
    # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
    permissions:
      contents: read
      packages: write
      
      
      #
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      # 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 }}
      
```

上記のワークフローは、"リリース" ブランチへのプッシュによってトリガーされます。 GitHub リポジトリをチェックアウトし、`login-action` を使用して Container registry にログインします。 その後、Docker イメージのラベルとタグを抽出します。 最後に、 `build-push-action` アクションを使用してイメージをビルドし、 Container registryに発行します。

## イメージを Docker Hub および GitHub Packages に発行する

> \[!NOTE] 現在、Container registry は パブリック プレビュー に対して GitHub Enterprise Server 段階であり、変更される可能性があります。

GitHub Packages を使うには、Container registry と Subdomain Isolation の両方を有効にする必要があります。 詳しくは、「[コンテナレジストリの利用](/ja/enterprise-server@3.22/packages/working-with-a-github-packages-registry/working-with-the-container-registry)」をご覧ください。

単一のワークフローで、各レジストリに対して `login-action` および `build-push-action` アクションを使用して、Docker イメージを複数のレジストリに公開できます。

次のワークフロー例では、前のセクションの手順 ([イメージをDocker Hub](#publishing-images-to-docker-hub)に公開し、[イメージを GitHub Packages](#publishing-images-to-github-packages) に公開) して、両方のレジストリにプッシュする単一のワークフローを作成します。

```yaml copy
# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

name: Publish Docker image

on:
  release:
    types: [published]

jobs:
  push_to_registries:
    name: Push Docker image to multiple registries
    runs-on: [self-hosted]
    permissions:
      packages: write
      contents: read
    steps:
      - name: Check out the repo
        uses: actions/checkout@v6

      - 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: containers.HOSTNAME
          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
            containers.HOSTNAME/${{ 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 }}
```

上記のワークフローでは、 GitHub リポジトリをチェックアウトし、 `login-action` を 2 回使用して両方のレジストリにログインし、 `metadata-action` アクションを使用してタグとラベルを生成します。
その後、`build-push-action` アクションによって Docker イメージがビルドされ、Docker HubとContainer registryにプッシュされます。

## ハンズオン プラクティス

Docker イメージの発行に関する[Docker イメージ発行](https://github.com/skills/publish-docker-images)GitHub Skillsの演習を行います。

この演習では、次の方法を学習します。

* GitHub Packagesを使用して`GITHUB_TOKEN`に対して認証します。
* コンテナー イメージをビルドして Container registry に発行します (`ghcr.io`)。
* `docker/login-action`、`docker/build-push-action`、`docker/setup-buildx-action`などの公式の Docker アクションを使用します。
* ブランチ、プル要求、リリースに基づいて、 `docker/metadata-action` を使用してタグを自動的に生成します。
* 適切なコンテナーのバージョン管理を使用して、機能、プル要求、リリースを作成します。