• 作成:

GitHub CLIの一時的なトークンを使ってGitHub Packagesからdockerイメージをpullするお手軽な方法

背景

開発時にメンバーが同じDockerイメージを使ってトラブル時に簡単に問題の再現を共有できるように、雑にCIするときにGitHub PackagesにDockerイメージをpushするようにしています。

どうせCIではdocker buildしていますからね。突然Dockerイメージがビルド出来なくなったら悲惨なのでCIではどうせビルドする必要があります。それならpushしても大した時間コストにはならないので雑に行って問題ありません。

GitHub ActionsでのCIのステップの一部

push

以下のように仕込んでやって、 bake定義を雑に書いておけば、後はビルド時にtagがついて毎回pushされます。

- id: meta
  uses: docker/metadata-action@v5
  with:
    images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: docker/login-action@v3
  with:
    registry: ${{ env.REGISTRY }}
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/bake-action@v6
  with:
    files: |
      ./docker-bake.hcl
      cwd://${{ steps.meta.outputs.bake-file }}
    push: true
  env:
    CACHIX_AUTH_TOKEN: "${{ secrets.CACHIX_AUTH_TOKEN }}"

cleanup

GitHub Packagesを無料枠で収めるために雑に古いイメージを消去する必要があります。

以下のステップを日本時間で6時に毎日実行するようにしています。

- uses: dataaxiom/ghcr-cleanup-action@v1
  with:
    exclude-tags: master # masterタグは除外
    keep-n-tagged: 10 # タグ付きイメージは最新10個保持
    keep-n-untagged: 10 # タグなしイメージは最新10個保持
    delete-ghost-images: true
    delete-partial-images: true
    delete-orphaned-images: true

厳密にイメージを管理するならもう少し真面目に考える必要があるのでしょうが、とりあえず我々にはこれで十分です。

問題

ここに挙げているdockerイメージをpullする方法を尋ねられました。

考えてみるとリポジトリがprivateだし、 GitHub Enterprise Cloud なのは混乱の原因です。

検索して出てくる既存の解決策

とりあえずClaudeに聞いてみたら、 PATとしてトークンを新しく払い出すという方法が提案されました。

永続的なトークンをむやみに作成したくないし、トークン生成というそれぞれのユーザのアカウントに依存するGUIの作業を他の人に依頼したくないです。

解決策

GitHub CLI からトークンを生成する方法で解決を試みます。

以下の手順で私の環境ではpullすることに成功しました。 YOUR_GITHUB_USERNAMEは自分のGitHubユーザ名に、 YOUR_ORG/YOUR_PACKAGEは実際のorganization名とパッケージ名に置き換えてください。

gh auth refresh -s read:packages
gh auth token | docker login ghcr.io --username YOUR_GITHUB_USERNAME --password-stdin
docker pull ghcr.io/YOUR_ORG/YOUR_PACKAGE

解説

gh auth tokenでトークンは生成できます。しかしデフォルトの状態では403エラーでpullできません。

gh auth statusで確認すると、以下のような表示になりました。

github.com
  ✓ Logged in to github.com account ncaq (/home/ncaq/.config/gh/hosts.yml)
  - Active account: true
  - Git operations protocol: https
  - Token: gho_************************************
  - Token scopes: 'gist', 'read:org', 'repo', 'workflow'

トークンのスコープにpackages関連が含まれていないことがわかります。

なのでgh auth refresh -s read:packagesでトークンにスコープを追加してやれば問題解決します。もちろん認証をリフレッシュする必要があるので実行する時はWebブラウザなどでログインする作業が必要です。