Github ActionsでGithub Container RegistryにDocker imageをpushする最小Workflow

公式ではstarter-workflowsとしてDocker imageをbuildをしてGithub Container RegistryにpushするまでのWorkflowが用意されていますが、アクションを使っておらず泥臭くやっているので本記事でアクションを使ったWorkflow構成を記載します。

- [starter-workflows/docker-publish.yml at main · actions/starter-workflows](https://github.com/actions/starter-workflows/blob/main/ci/docker-publish.yml)

# 前提
今回取り扱うリポジトリのファイル構成はルート直下にDockerfileが存在するものとします。

```
-- 
|-- Dockerfile
|-- README.md
|-- .github
    |-- workflows
        |-- actions.yml
...
```

# 解

```yml:.github/workflows/action.yml
name: Build and Publish Docker

on:
  push:
    branches:
      - master

jobs:
  build_and_push:
    runs-on: ubuntu-latest
    env:
      IMAGE_NAME: sample-app
    steps:
      - name: checkout
        uses: actions/checkout@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.CR_PAT }}

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: |
            ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:latest
            ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:1.0.0
```

# ワークフロー解説
本ワークフローでは`build_and_push`というジョブを定義しています。
以降はそのジョブ内の各ステップが何をしているか軽く解説します。

## checkout
ソースコードをcheckoutします。
`actions/checkout@v2`アクションを利用しています。

- [Checkout · Actions · GitHub Marketplace](https://github.com/marketplace/actions/checkout)

## Set up Docker Buildx
`docker/build-push-action@v2`アクションで`docker build`のための必要なセットアップをここで行っています。
`docker/setup-buildx-action@v1`アクションを利用しています。

- [Docker Setup Buildx · Actions · GitHub Marketplace](https://github.com/marketplace/actions/docker-setup-buildx)

## Login to GitHub Container Registry
GitHub Container Registryにdocker imageをpushするためにここで`docker login`を行います。
`docker/login-action@v1`アクションを利用します。
`with`で必要なパラメータを定義します。

|パラメータ|値|
|:-:|:-:|
|registry|Dockerレジストリを指定する<br>今回はGithub Container Registryにpushするので`ghcr.io`を指定<br>未指定の場合はDocker Hubになる|
|username|Dockerレジストリにpushするユーザを指定する<br>今回はリポジトリオーナー名を環境変数から指定※1|
|password|DockerレジストリにpushするパスワードもしくはPersonal Access Tokenを指定する<br>今回はsecretsにCF_PATという名前で格納したPersonal Access Tokenを指定※2|

- [Docker Login · Actions · GitHub Marketplace](https://github.com/marketplace/actions/docker-login)

※1: Github Actionsではデフォルトでいくつかの環境変数が用意されており、今回はその中から取得しました。
参考：[Environment variables - GitHub Docs](https://docs.github.com/ja/free-pro-team@latest/actions/reference/environment-variables)

※2: シークレットの設定方法はこちらを参照。
[Encrypted secrets - GitHub Docs](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets)


## Build and push
`docker build`と`docker push`を行います。
`docker/build-push-action@v2`アクションを利用しています。
`with`で必要なパラメータを定義します。

|パラメータ|値|
|:-:|:-:|
|context|`docker build`する際のパスもしくはURLを指定<br>`actions/checkout`アクションを使った場合にパスの指定が可能<br>今回はcheckoutしたルート配下を指定<br>未指定の場合はGit contextとなる|
|push|Dockerレジストリにpushする場合はtrueを指定|
|tags|buildするimageにつけるタグを指定<br>タグは複数指定可能<br>今回はlatestと1.0.0のタグを付与|
|file|参照するDockerfileパスを指定<br>未指定の場合は`./Dockerfile`となる<br>今回はこのパラメータは使用していないがルート直下以外のDockerfileを参照する場合は使用する|

- [Build and push Docker images · Actions · GitHub Marketplace](https://github.com/marketplace/actions/build-and-push-docker-images)

# 参考
- [Migrating to GitHub Container Registry for Docker images - GitHub Docs](https://docs.github.com/ja/free-pro-team@latest/packages/getting-started-with-github-container-registry/migrating-to-github-container-registry-for-docker-images)