ロボットアカウントから GitHub Container Registry(GHCR)を使う

2021/04/15: GitHub Actions のワークフローで GITHUB_TOKEN を使って ghcr.io で認証できるようになりました。個々のコンテナイメージ毎に特定のリポジトリのワークフローで READ/WRITE のどちらを許可するのか選択できます。詳しくは Packages: Container registry now supports GITHUB_TOKEN - GitHub Changelog を参照ください。

はじめに

Docker Hub の Rate Limit の件もあり、新しくイメージをホストするコンテナレジストリとして GitHub Container Registry(GHCR)を使ってみようとしましたが、ロボットアカウントから使用するのにいくつかハマりポイントがあったので残します。

なぜロボットアカウントを使うのか

ロボットアカウントとは、ここでは開発者アカウントに紐付かず一般に特定の用途、例えばここではコンテナイメージのアップロード(プッシュ)のみに使用するアカウントのことを指します。GitHub には「ロボットアカウント」機能は存在しないので、一般のアカウントを作成しロボットアカウントとして使用することになります。

なぜ GHCR をロボットアカウントから使用する必要があるかというと、それは GHCR が GitHub Actions ワークフローの GITHUB_TOKEN のトークンではイメージをアップロードできないためです。

Add your new container registry authentication personal access token (PAT) as a GitHub Actions secret. GitHub Container Registry does not support using GITHUB_TOKEN for your PAT so you must use a different custom variable, such as CR_PAT.

そのため、上記にあるとおりにパーソナルアクセストークン(PAT)を用意しないといけないのですが、個人リポジトリなら個人で払い出したトークンでよいのですが、チームや他の人とともに管理しているリポジトリだと個人のトークンは使用したくありません。そこで、新たにロボットアカウントとしてアカウントを作成して、そのアカウントでトークンを払い出して使おうということです。

ロボットアカウントの管理は面倒なのでやりたくありませんが、個人のトークンが使われるよりはマシです。

個人の見解: GITHUB_TOKEN でイメージをアップロードできないのは、GHCR が Org レベルで存在しているためだと思っています。GitHub Actions ワークフローの GITHUB_TOKEN はそのリポジトリを操作できる権限を持つトークンなので、Org レベルで場所が用意されている GHCR はそのトークンでは操作させられないはずです。GHCR はリポジトリごとに場所が作られる仕様でよかったんじゃないかなと思わなくもないです。

1. ロボットアカウントを Org に参加させる

ロボットアカウントを作成したら次にそのアカウントを Org のメンバとして参加させます。ここで外部のコラボレータ(Outside collaborator)として Org 内の特定のリポジトリに参加させてもイメージをアップロードできないことに注意してください。

メンバへの追加は https://github.com/orgs/{org}/people の「Invite member」ボタンから行えます。

Invite member ボタン

2. メンバの「パッケージ作成」を許可する

Org のメンバはデフォルトだとパッケージ、ここではコンテナイメージのアップロードができません。https://github.com/organizations/{org}/settings/member_privileges の「Package creation」でイメージのアップロードを許可します。ここでは “Public” または “Private” どちらでアップロードできるかを選択できます。ここでは “Public” にします。

Package creation でパッケージの作成を許可

3. ロボットアカウントのパーソナルアクセストークンを作成

ロボットアカウントでパーソナルアクセストークンを作成します。ロボットアカウントで GitHub にアクセスした状態で https://github.com/settings/tokens/new にアクセスします。ここでトークンのスコープには write:packages を選択します。

write:packages のスコープでトークンを作成

作成されたトークンはメモしておきます。

4. Organization secrets としてトークンを登録

GitHub Actions でトークンを参照するために Organization secrets としてトークンを登録します。Org secrets の登録は https://github.com/organizations/{org}/settings/secrets からできます。Secret 名は GHCR のドキュメントに従って CR_PAT なりにします。

PAT を Org secrets として登録

特定リポジトリの Secrets として保存するのでも問題ないのですが、トークン自体は Org レベルで有効なため、Org secrets として作成し、リポジトリに不要にトークンを払い出すのを避けたほうがよいかなと思います。

これで GitHub Actions ワークフローから ${{ secrets.CR_PAT }} でトークンを参照できます。

5. GitHub Actions ワークフローの定義

さいごに GitHub Actions でイメージをビルドしアップロードするサンプルのワークフローを示します。

name: Release

on:
  push:
    tags: ["v*"]

jobs:
  run:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Login to GitHub Container Registry
      run: echo "$CR_PAT" | docker login ghcr.io --username "$GITHUB_ACTOR" --password-stdin
      env:
        CR_PAT: ${{ secrets.CR_PAT }}
    - name: Build image
      run: docker build ghcr.io/my_org/my_app:${{ github.event.inputs.tag }} .
    - name: Push image to GitHub Container Registry
      run: docker push ghcr.io/my_org/my_app:${{ github.event.inputs.tag }}

ほかのコンテナレジストリの選択肢は

パブリックで使用できる他の選択肢として Red Hat 社が運営する Quay.io があります。こちらにはロボットアカウント機能があります。

さいごに

GHCR の基本的な使用については下記を参照ください。