GHCR (GitHub Container Registry) とは — Docker Hub との違い、使い方、料金

読了 7分

CI のログや docker-compose.yml で、ghcr.io/... で始まるイメージ名を見かけることが増えてきました。GHCR (GitHub Container Registry) は GitHub が運営するコンテナイメージのレジストリです。コードが GitHub にあるならイメージも同じ場所に置く、という流れが標準のように定着していて、その中心にあるサービスです。

この記事は GHCR に初めて触れる方を想定して、四つの質問に答えます。

  • GHCR とは正確には何か
  • Docker Hub と何が違うのか
  • 料金はいくらか
  • どう使うのか (push/pull、GitHub Actions)

push/pull コマンド自体が初めてなら、先に Docker 基礎 #5 レジストリ を読むのがおすすめです。この記事はその中の GHCR を正面から掘り下げます。

GHCR とは #

GHCR は、GitHub Packages というパッケージホスティングサービスのコンテナ部門です。アドレスは ghcr.io で、OCI (Open Container Initiative) 標準に従うレジストリなので、Docker から見れば Docker Hub とまったく同じように動きます。docker logindocker pushdocker pull の流れがそのまま使えて、podman や Helm チャート (OCI アーティファクト) のような他のツールでも利用できます。

イメージ名はこの形です。

GHCR イメージ名の構造
ghcr.io/OWNER/IMAGE_NAME:TAG

ghcr.io/curtis/hello-docker:1.0
        ─────  ────────────  ───
     アカウント/組織  イメージ名   タグ

OWNER は GitHub のアカウント名または組織名で、すべて小文字である必要があります。GitHub アカウントが MyName なら、イメージのパスは ghcr.io/myname/... になります。

一つだけ概念を押さえておくと、残りが楽になります。GHCR に上がったイメージは、GitHub 上ではパッケージ (package) という独立した単位で管理されます。コードリポジトリに従属するのではなくアカウント/組織の下に存在し、必要なら特定のリポジトリと紐付けられます。公開範囲 (public/private) もリポジトリではなくパッケージ単位で決めます。

Docker Hub と何が違うのか #

Docker を学ぶとき最初に出会うレジストリは、たいてい Docker Hub です。しかし実務で自分のサービスのイメージを置く場所を選ぶ段階になると、GHCR が先に検討されることが多くなります。違いを表にまとめるとこうなります。

Docker HubGHCR
運営主体DockerGitHub
公式イメージ (python, nginx など)ありなし
pull 回数制限未認証 100 回/6 時間 (IP 単位)、無料アカウント 200 回/6 時間公表された回数制限なし
権限モデルDocker Hub の別アカウントと組織GitHub のアカウント、組織、チーム権限をそのまま利用
private リポジトリ無料プランは 1 個、それ以上は有料プラン個数制限なし、現在無料 (下の料金の節を参照)
GitHub Actions 連携別途シークレット登録が必要GITHUB_TOKEN で即認証

実務の感覚で要約するとこうなります。

ベースイメージは Docker Hub から来ます。 python:3.14-slimnginx:1.27 のような公式イメージは Docker Hub にしかありません。GHCR をメインのレジストリにしても、Dockerfile の FROM は Docker Hub を向いているケースがほとんどです。

pull 制限は CI で体感します。 Docker Hub は未認証の状態では IP あたり 6 時間に 100 回で pull を制限します。問題は、CI 環境 (GitHub Actions、GitLab CI など) が IP を他のユーザーと共有している点です。自分は数回しか pull していなくても、同じ IP の別のビルドが上限を使い切って toomanyrequests エラーに遭遇することがあります。GHCR は公式ドキュメントに公表された pull 回数制限がないため、自分のサービスのイメージを GHCR に置けばこの問題から抜け出せます。

権限管理が一つにまとまります。 Docker Hub を使うと、メンバーのアカウントと権限を GitHub と Docker Hub の二箇所で管理することになります。GHCR は GitHub の組織とチーム権限をそのまま使うので、リポジトリへのアクセス権を持つ人にイメージへのアクセス権を与える作業が、設定一回で済みます。

料金 — 今は無料 #

GHCR の検索でよく出てくる質問なので、独立した節にします。結論から言うと、コンテナレジストリのストレージと帯域は現在無料です。 public イメージでも private イメージでも同じです。GitHub の公式ドキュメントが「currently free」と明記していて、課金を始める場合は最低 1 か月前に告知するとしています。

課金が始まった場合の基準もドキュメントにあります。GitHub Packages の一般的な料金体系は、private パッケージに対してプランごとの無料枠を設ける方式です。

プランストレージ月間転送量 (ダウンロード)
Free500MB1GB
Pro2GB10GB
Team2GB10GB
Enterprise Cloud50GB100GB

二つのケースは課金対象から外れます。public パッケージは無条件で無料、そして GitHub Actions の中で GITHUB_TOKEN を使って受け取る転送量も課金されません。 つまりビルドとデプロイが GitHub Actions の中で回る構成なら、課金が始まっても負担が大きくならないように設計されています。

数字は 2026 年 7 月のドキュメント基準です。料金ポリシーは変わる可能性があるので、判断の前に GitHub Packages billing のドキュメントを一度確認してください。

使い方 — トークン発行から pull まで #

1. PAT (classic) を作る #

GHCR の認証には GitHub のパスワードではなく PAT (Personal Access Token) を使います。ここで注意点が一つ。GitHub には新型の fine-grained PAT と旧型の classic PAT がありますが、レジストリの認証にはまだ classic PAT しか使えません。

GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) でトークンを作り、権限にチェックを入れます。

  • push までするなら write:packages
  • pull だけなら read:packages
  • パッケージの削除もするなら delete:packages

2. ログイン #

GHCR ログイン
export CR_PAT=ghp_xxxxxxxxxxxxxxxxxx
echo $CR_PAT | docker login ghcr.io -u curtis --password-stdin
# Login Succeeded

トークンを --password-stdin で渡せば、シェルの履歴に残りません。

3. タグを付けて push #

イメージ名に ghcr.io/アカウント名 が入っていて初めて、Docker は送り先が分かります。

タグ + push
docker tag hello-docker ghcr.io/curtis/hello-docker:1.0
docker push ghcr.io/curtis/hello-docker:1.0

4. 公開範囲を変える #

最初に push したパッケージはデフォルトで private です。公開するには、GitHub の該当パッケージページ → Package settings → Change package visibility で public に変えます。public になれば、誰でもログインなしで pull できます。

public イメージはログインなしで pull
docker pull ghcr.io/curtis/hello-docker:1.0

5. リポジトリと紐付ける #

Dockerfile にラベルを一行入れると、イメージがコードリポジトリと紐付きます。

Dockerfile — リポジトリ紐付けラベル
LABEL org.opencontainers.image.source=https://github.com/curtis/hello-docker

紐付けるとリポジトリページのサイドバーにパッケージが表示され、リポジトリの README がパッケージページに載ります。リポジトリの権限をパッケージに継承させる起点にもなるので、実務では入れるのを基本にしておけばよいです。

GitHub Actions では — PAT なしで #

GHCR を選ぶ最大の理由がこの部分です。GitHub Actions の中ではワークフローごとに自動発行される GITHUB_TOKEN があるので、PAT を作ってシークレットに登録する手順が丸ごと不要になります。

.github/workflows/build.yml (核心部分)
permissions:
  contents: read
  packages: write

steps:
  - uses: docker/login-action@v3
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - uses: docker/build-push-action@v6
    with:
      push: true
      tags: ghcr.io/${{ github.repository_owner }}/myapp:${{ github.sha }}

permissionspackages: write を明示することだけ忘れなければ大丈夫です。タグをコミット SHA で打つ理由と :latest だけに頼ってはいけない理由は、Docker 実戦 #5 タグ戦略 で詳しく扱いました。

運用のコツ二つ #

古いバージョンの整理。 CI がコミットごとにイメージを push すると、untagged のバージョンが溜まり続けます。今は無料なので放置してもコストはかかりませんが、パッケージページが散らかり、課金開始時の負担にもなります。actions/delete-package-versions アクションで古いバージョンを定期的に消すワークフローを一つ入れておくときれいに保てます。

ダイジェストでの固定。 タグは同じ名前で再 push される可能性があります。再現性が重要なデプロイなら、ghcr.io/curtis/myapp@sha256:... 形式のダイジェスト参照を使ってください。これは GHCR に限った話ではなく、すべてのレジストリに共通です。

まとめ — どのレジストリを選ぶか #

  • コードが GitHub にあり、GitHub Actions でビルドする — GHCR がデフォルトの選択です。認証、権限、料金のすべてで摩擦が最も少なくなります。
  • 公式ベースイメージ — Docker Hub から取得します。選択の問題ではなく、そこにしかありません。
  • AWS にデプロイする (ECS、EKS) — 同じネットワークの中にある ECR も併せて検討する価値があります。転送の遅延とコストで有利な場合があります。

GHCR は「GitHub を使っているなら迷う理由があまりない」レジストリです。無料で、pull 制限がなく、権限管理が GitHub に統合されています。レジストリの概念自体に馴染みがなければ Docker 基礎 #5 から、CI パイプライン全体が気になるなら Docker 実戦シリーズ へ進んでください。

X