こんにちは、 id:rokuokun です。
Docker Hub の利用制限がいよいよ厳しくなってきたので、これを機に全部 GitHub Container Registry にアップロードしちゃいましょう。
せっかくなら GitHub Actions を使っていい感じにやります。
Docker Hub の Rate Limit
Starting April 1, 2025, all users with a Pro, Team, or Business subscription will have unlimited Docker Hub pulls with fair use. Unauthenticated users and users with a free Personal account have the following pull limits:
- Unauthenticated users: 10 pulls/hour
- Authenticated users with a free account: 100 pulls/hour
認証ユーザーでも1時間あたり 100 回しか pull できないのでそれなりに辛い感じになりました。
ビルド時に pull するのは仕方ないとして、成果物は GitHub Container Registry(GHCR) においておけばこの Rate Limit をある程度回避できます。
Docker Hub の PAT を発行する
ベースイメージの Pull は Docker Hub からされるケースが多いと思うでの、Actions 内でも一度ログインされるようにします。
まず、docker account center の Personal Access Tokens から Personal Access Token (PAT) を作成します。 Permission は特に書き込みはしないので Read Only で良いでしょう。
Repository Settings から Secrets を登録しておきます。
Workflow を書いていく
実際に動いている様子は以下のリポジトリで見ることができます。 参考までにどうぞ。
上記リポジトリで動作している Workflow を以下に表示します。
name: image-build-and-push on: push: branches: - main pull_request: types: - opened - synchronize - reopened paths: - ".github/workflows/image-build-and-push.yaml" - "Dockerfile" workflow_dispatch: env: IMAGE_NAME: ghcr.io/${{ github.repository }}/sample jobs: build-and-push: runs-on: ubuntu-latest timeout-minutes: 10 permissions: contents: read pull-requests: read id-token: write packages: write steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PAT }} - uses: docker/metadata-action@v4 id: meta with: # コンテナイメージの名前を指定する。 # 以下の指定指定方法だと以下のようなイメージが作成される。 # ghcr.io/username/repository-name/sample:tag images: ${{ env.IMAGE_NAME }} # デフォルトブランチの時だけ latest タグをつけてそれ以外は日時とコミットハッシュをつける # ref: https://github.com/docker/metadata-action?tab=readme-ov-file#customizing tags: | type=raw,value=latest,enable={{is_default_branch}} type=raw,value={{date 'YYYYMMDD-HHmmss' tz='Asia/Tokyo'}}-{{sha}} # Open Container Initiative (OCI) の Image Spec に基づくラベル # ref: # - https://github.com/opencontainers/image-spec/blob/fbb4662eb53b80bd38f7597406cf1211317768f0/annotations.md?plain=1#L18-L26 labels: | org.opencontainers.image.authors=${{ github.repository_owner }} org.opencontainers.image.url=https://github.com/${{ github.repository }} org.opencontainers.image.documentation=https://github.com/${{ github.repository }} org.opencontainers.image.source=https://github.com/${{ github.repository }} - name: Build and push uses: docker/build-push-action@v6 with: context: . file: Dockerfile tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} provenance: false cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:cache cache-to: type=registry,ref=${{ env.IMAGE_NAME }}:cache,mode=max - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }}
ビルドキャッシュ
今回は丁寧にやるので Build するついでにキャッシュもできるようにしています。
キャッシュは docker/build-push-action
のcache-from
とcache-to
で行っていますが、デフォルトのドライバーでは実行できないため、 docker/setup-buildx-action
でdocker-container
ドライバを使用可能にしています。
詳細はそれぞれのドキュメントを見てください。
キャッシュで使用するコンテナイメージは :cache
というタグが付けられています。
イメージ詳細からタグ一覧を確認できます。
https://github.com/rokuosan/ghcr-example/pkgs/container/ghcr-example%2Fsample
Image Metadata
コンテナイメージにはラベルがあり、Open Container Initiative がイメージにつけるラベルを決めてくれています。 今回はそれに従う形でラベルを付けてみました。
イメージに対してラベルをつける作業は docker/metadata-action
で行っています。
実際につけられたラベルは GitHub Actions のログから確認できます。
${{ github.owner }}
で出した自分の名前がマスクされていますが、実際に Pull して中身を見てみるとしっかりとラベル付けられていることが確認できます。
ラベルとつけると一気に丁寧感が出ました。
$ docker pull ghcr.io/rokuosan/ghcr-example/sample:latest $ docker inspect ghcr.io/rokuosan/ghcr-example/sample:latest | jq ".[0].Config.Labels"
{ "org.opencontainers.image.authors": "rokuosan", "org.opencontainers.image.created": "2025-02-25T12:48:29.182Z", "org.opencontainers.image.description": "", "org.opencontainers.image.documentation": "https://github.com/rokuosan/ghcr-example", "org.opencontainers.image.licenses": "", "org.opencontainers.image.revision": "65c41aa9dbb0f351c6d99f668c3f3120a2eb8188", "org.opencontainers.image.source": "https://github.com/rokuosan/ghcr-example", "org.opencontainers.image.title": "ghcr-example", "org.opencontainers.image.url": "https://github.com/rokuosan/ghcr-example", "org.opencontainers.image.version": "latest" }
詳しく知りたい方はこちらからどうぞ。
その他
書くことでもないですが Workflow の起動タイミングや Image の Push タイミングを少しだけ調整しています。
これで少し丁寧ポイントが上がりました。
おわりに
各言語の公式イメージなどが GitHub Container Registry にあればさらにレートリミットの影響を受けなくてすみますが、もしそうなると利用率がさらに増えて今度は ghcr が制限されるということになりそうですね。
ghcr でも特に困ることはほとんどないので、今後イメージを作るなら全部 ghcr でいいじゃんという気持ちになっています。(各クラウドのコンテナレジストリは別の話題ということで)