Actionsから自動でGitHub Container Registry(ghcr.io)にDockerイメージをpushする

# はじめに
2020年9月からghcr.ioがパブリックベータ版として公開され、DockerイメージレジストリとしてGitHubアカウントさえあれば、誰でも利用できるようになりました。

[team-shahu](https://github.com/team-shahu)にて開発を行っている[misskeyのフォーク](https://github.com/team-shahu/misskey)では、Actionsを用いて自動でghcr.ioへイメージをpushしているので、その知見を踏まえながら、コンテナをビルドしghcr.ioへpushする手順を紹介します。

# GitHub Actionsとは？
GitHub ActionsはGitHub上で稼働するワークフロー自動化サービスです。
GitHub Actionsではリポジトリに対するプッシュなどの処理をトリガーとして、専用のファイルに定義しておいた処理を自動で実行できます。

https://github.co.jp/features/actions

ghcr.ioにおいては、Actionsを利用することで、データ転送に課金されないことやログイン情報を指定する必要がない利点があります。

# GitHub Actionsでコンテナイメージをpushする
実際に動いているファイルはこんな感じ。

```yaml:.github/workflows/docker.yaml
name: Publish Docker image

on:
  release:
    types: [published]
  workflow_dispatch:

env:
  REGISTRY_IMAGE: misskey/misskey
  TAGS: |
    type=edge
    type=ref,event=pr
    type=ref,event=branch
    type=semver,pattern={{version}}
    type=semver,pattern={{major}}.{{minor}}
    type=semver,pattern={{major}}

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        platform:
          - linux/amd64
          - linux/arm64
    if: github.repository == 'team-shahu/misskey'
    steps:
        # 静的なファイルとして保存する
      - uses: actions/checkout@v3
        # メタデータを抽出する
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY_IMAGE }}
          tags: ${{ env.TAGS }}
        # ghcr.ioへログインする
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
        # ビルド
      - name: Build Docker Image
        run: |
          docker build --tag ghcr.io/${{ github.repository_owner }}/misskey:latest \
          --tag ghcr.io/${{ github.repository_owner }}/misskey:$${{ steps.meta.outputs.version }} \
          .
        # pushする
      - name: Push Docker Image
        run: |
          docker push ghcr.io/${{ github.repository_owner }}/misskey:latest
          docker push ghcr.io/${{ github.repository_owner }}/misskey:$${{ steps.meta.outputs.version }}
```

Actionsの基本構文には触れず、ここではjobsの中身だけを上から順に説明していきます。

## 静的なファイルとして保存する
```yaml
- uses: actions/checkout@v3
```
の部分です。
やってることは、Actionsの実行環境に当該repoをcloneしてローカル参照できるようにしているだけです。

## メタデータを抽出する
```yaml
- name: Docker meta
    id: meta
    uses: docker/metadata-action@v5
    with:
      images: ${{ env.REGISTRY_IMAGE }}
      tags: ${{ env.TAGS }}
```
の部分です。
ここでは、コンテナイメージに付与するタグをいい感じに設定しています。

上の方の`env`で記述していた

```yaml
TAGS: |
    type=edge
    type=ref,event=pr
    type=ref,event=branch
    type=semver,pattern={{version}}
    type=semver,pattern={{major}}.{{minor}}
    type=semver,pattern={{major}}
```

これらのものが指定されます。

詳しい説明詳細は[この辺](https://github.com/docker/metadata-action#tags-input)を参照してください。

## ghcr.ioへログインする
```yaml
- name: Login to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
```
この部分です。

CLを使う場合と同様に、最初にghcrへログインを行う必要があります。
自前でスクリプトを用意するのは大変なので、今回は[login-action](https://github.com/docker/login-action)を用いました。

ちなみに、`GITHUB_TOKEN`を自分でsecretsに登録する必要はありません。
Actionsを使うと`${{ secrets.GITHUB_TOKEN }}`としてあげるだけで認証できるのでいいですよね。

## Dockerイメージのビルド
```yaml
- name: Build Docker Image
    run: |
      docker build --tag ghcr.io/${{ github.repository_owner }}/misskey:latest \
      --tag ghcr.io/${{ github.repository_owner }}/misskey:$${{ steps.meta.outputs.version }} \
      .
```
この部分です。
タグを付与してビルドしてるだけですね。
CLI上でやる時と変わりません。

## ghcr.ioへpushする
```yaml
- name: Push Docker Image
    run: |
      docker push ghcr.io/${{ github.repository_owner }}/misskey:latest
      docker push ghcr.io/${{ github.repository_owner }}/misskey:$${{ steps.meta.outputs.version }}
```
この部分です。

ghcr.ioへビルドしたイメージをpushしています。
CLI上でやるものと同様のコマンドを実行しているだけなので何も変わりません。

# 実行してみる
適当なタグを指定してリリースを出してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/7562cb85-71d1-c878-5f3b-c538952e02ff.png)

しばらくするとActionsが動き始め、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/90f44e43-b10a-d74f-e353-138f5bf844a9.png)

イメージが追加されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/966ae374-8ec3-721f-c987-6190c11772d7.png)

これを実行環境からpullしてあげるとそのまま動きます。


# さいごに
この記事では、Actionsを用いて、GitHub Container Registryにコンテナイメージをpushする方法をまとめました。
GitHub上だけで開発から公開まで完結できるのはいいですよね。

今回のフローでは、ビルドとpushをRUNでコマンドのまま扱っていましたが、[docker/build-push-action](https://github.com/docker/build-push-action)を使うともう少し簡単にかけたかもしてません。(聞くところによるとキャッシュも使えるらしい。)


この記事が誰かのお役に立てれば幸いです。

それでは。