Docker Hub か GHCR か:どちらが最適?
もしあなたが Docker Hub からイメージをプルする際に Too Many Requests エラーに遭遇したことがあるなら、そのもどかしさがよくわかるはずです。Docker Hub の無料プランでは、6時間あたり200プルまでに制限されています。この制限は、CI/CD システムを頻繁に回していると、あっという間に上限に達してしまいます。さらに、無料プランで作成できるプライベートリポジトリは1つだけです。
それが、私が GitHub Container Registry (GHCR) に完全に移行した理由です。個人プランであれば、500MBのストレージと月間1GBの帯域幅が完全に無料で利用できます. ソースコードからイメージまで、すべてを GitHub という一つの場所にまとめられるため、管理も格段に楽になります。
クイックスタート:5分で Docker イメージを GHCR にプッシュする
新しいツールをインストールする必要はありません。ターミナルに Docker がインストールされていれば準備完了です。
ステップ 1:Personal Access Token (PAT) の作成
GitHub では、セキュリティのために通常のパスワードの代わりにトークンを使用します。Settings > Developer settings > Personal access tokens > Tokens (classic) にアクセスし、以下の項目にチェックを入れます。
write:packages: イメージをアップロードするため。read:packages: サーバーにイメージをダウンロードするため。delete:packages: 古いイメージを削除するため。
ステップ 2:CLI でログイン
トークンを環境変数に保存し、次のコマンドでログインします。
export CR_PAT=YOUR_TOKEN
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
ステップ 3:イメージのタグ付けとプッシュ
ローカルにあるイメージ名が my-app だとします。GHCR の標準に従ってタグを付け、プッシュします。
# タグ付けの形式: ghcr.io/username/image-name:version
docker tag my-app ghcr.io/username/my-app:v1.0
# レジストリにプッシュ
docker push ghcr.io/username/my-app:v1.0
GitHub プロフィールの Packages セクションを確認すると、イメージが安全に保存されていることがわかります。
GHCR の仕組みの特徴
Docker Hub とは異なり、GHCR は Organization または User に密接に紐付いています。これは権限管理において非常に便利です。イメージを Private に保ちながら、特定のリポジトリに対してのみアクセス権を付与することができます. サーバー上で面倒な SSH キーの設定や手動ログインを行う必要はもうありません。
GitHub Actions による自動化
これこそが最も価値のある部分です。手動でビルドする代わりに、GitHub Actions を使ってワークフローを自動化しましょう。git push するだけで、新しいイメージが自動的にデプロイされます。
以下は、Node.js プロジェクトでよく使われるワークフローのサンプルファイル (.github/workflows/publish.yml) です。
name: Build and Push Docker Image
on:
push:
branches: ["main"]
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: リポジトリのチェックアウト
uses: actions/checkout@v4
- name: GHCR にログイン
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: ビルドとプッシュ
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
ここでのポイントは ${{ secrets.GITHUB_TOKEN }} です。これは自動生成されるトークンで、Action の実行中のみ有効です。固定の PAT を使用するよりもはるかに安全です。
リポジトリのアクセス権限管理のコツ
サーバーや別のリポジトリからプライベートイメージをプルするにはどうすればよいでしょうか? その答えは Manage Actions access 機能にあります。
- GitHub プロフィールの Packages にアクセスします。
- 対象のイメージを選択し、Package settings をクリックします。
- 下部にある Manage Actions access セクションを探します。
- Add repository をクリックし、権限を付与したいリポジトリを検索します。
- 権限を Read に設定すれば、そのサーバーから自由にプルできるようになります。
この方法により、メインアカウントを共有することなく、誰がイメージを使用できるかを厳密に制御できます。
コストを最適化するための実践的なヒント
itfromzero のプロジェクトで長期間 GHCR を使用してきた経験から、いくつかのアドバイスがあります。
- 定期的なクリーンアップ: GHCR は最初の 500MB まで無料です。イメージが重い場合(例:1イメージ 200MB)、3回ビルドするだけで容量がいっぱいになります。30日後に古いイメージを自動削除する Action を導入しましょう。
- マルチステージビルドの活用: Dockerfile を最適化してください。Alpine をベースにした Node.js イメージは約 100MB ですが、フルバージョンは 1GB に達することもあります。イメージを軽量化することで、プッシュ/プルが高速になり、容量も節約できます。
- トークンのセキュリティ: PAT を YAML ファイルにハードコードしないでください。常にデフォルトの
GITHUB_TOKENを優先的に使用しましょう。 - 事前にローカルでテストする: 単純な構文エラーの修正のために CI/CD リソースを浪費しないようにしましょう。プッシュする前に、ローカル環境の Docker Compose で動作確認を行ってください。
GHCR に切り替えたことで、VPS へのデプロイフローが非常にスムーズになりました。一度ログイン設定をすれば、あとはスクリプトを通じてすべてが自動で動きます。この記事が、皆さんの GHCR 導入の助けになれば幸いです。YAML の設定などでエラーが出た場合は、ぜひ下のコメント欄で質問してください!

