GitHub Packagesをちゃんと理解する
1. はじめに
GitHub Packagesは、ソースコードとパッケージを一元管理できるプラットフォームです。これまでnpmやDockerHubなど、複数のサービスにパッケージを分散させていた開発チームにとって、統合された管理環境は開発効率の大幅な向上をもたらします。本記事では、GitHub Packagesの仕組みと実践的な活用方法について解説します。
2. GitHub Packagesの基本構造
GitHub Packagesは、多様なパッケージマネージャーに対応したホスティングサービスです。単一のプラットフォーム上で、言語やエコシステムの垣根を超えたパッケージ管理が可能になります。
2.1 サポートされているパッケージレジストリ
| 言語/用途 | パッケージマネージャー | 設定ファイル |
|---|---|---|
| JavaScript | npm | package.json |
| Ruby | RubyGems | Gemfile |
| Java | Apache Maven | pom.xml |
| Java | Gradle | build.gradle |
| .NET | NuGet | nupkg |
| コンテナ | Docker/OCI | Dockerfile |
これらのレジストリは、既存のツールチェーンをそのまま利用できるため、移行コストを最小限に抑えられます。
3. 権限モデルの理解
GitHub Packagesには2つの権限モデルが存在します。レジストリによってどちらのモデルを採用しているかが異なるため、適切な理解が必要です。
3.1 権限モデルの全体像
3.2 Granular Permissions(細かい権限設定)
Container registry、npm、NuGet、RubyGemsでは、パッケージごとに独立した権限設定が可能です。この方式では以下の柔軟性が得られます。
- パッケージの可視性をリポジトリと独立して設定
- ユーザーまたは組織単位でのアクセス制御
- リポジトリへのアクセス権とは別に、パッケージ単位で権限付与
3.3 Repository-scoped Permissions(リポジトリ連動型)
Apache MavenとGradleでは、パッケージがリポジトリの権限と可視性を継承します。リポジトリへのアクセス権を持つユーザーは、自動的にパッケージへのアクセスも可能になります。
4. アクセス制御の実装
パッケージには3つのアクセスレベルが定義されています。
| 権限レベル | できること |
|---|---|
| Read | パッケージのダウンロード メタデータの閲覧 |
| Write | パッケージのアップロードとダウンロード メタデータの読み書き |
| Admin | パッケージの完全な管理 削除や権限付与を含むすべての操作 |
4.1 権限継承の制御
Granular Permissionsをサポートするレジストリでは、パッケージとリポジトリの連携方法を選択できます。
組織のオーナーは、新規パッケージの自動継承をデフォルトで無効化することもできます。これにより、組織全体で一貫したパッケージ管理ポリシーを実現できます。
5. 認証とトークン管理
GitHub Packagesへのアクセスには、Personal Access Token(classic)が必要です。
5.1 必要なスコープ
トークンには用途に応じたスコープを設定します。
| スコープ | 用途 |
|---|---|
read:packages |
パッケージのダウンロードとインストール |
write:packages |
パッケージのアップロードと公開 |
delete:packages |
パッケージの削除(read:packagesも必要) |
5.2 GitHub Actionsでの認証
ワークフロー内ではGITHUB_TOKENを使用することで、トークンの管理が不要になります。
name: パッケージ公開
on:
push:
branches: [ main ]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: パッケージ公開
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker build -t ghcr.io/組織名/パッケージ名:latest .
docker push ghcr.io/組織名/パッケージ名:latest
ただし、GITHUB_TOKENでアクセスできるのはワークフローが実行されているリポジトリに関連付けられたパッケージのみです。他のプライベートリポジトリのパッケージにアクセスする場合は、Personal Access Tokenが必要になります。
6. コンテナイメージとリポジトリの連携
Dockerコンテナを公開する際、リポジトリと連携させることでメタデータが自動的に表示されます。
6.1 Dockerfileでの設定
FROM ubuntu:latest
# リポジトリとの連携を設定
LABEL org.opencontainers.image.source=https://github.com/ユーザー名/リポジトリ名
RUN apt-get update && apt-get install -y \
アプリケーション
COPY . /app
WORKDIR /app
CMD ["./起動スクリプト"]
6.2 ビルドとプッシュ
# イメージのビルド
docker build -t hello_docker .
# タグ付け
docker tag hello_docker ghcr.io/ユーザー名/hello_docker:latest
# Container registryへの認証
echo $CR_PAT | docker login ghcr.io -u ユーザー名 --password-stdin
# プッシュ
docker push ghcr.io/ユーザー名/hello_docker:latest
リポジトリと連携することで、パッケージページにREADMEや最近のコミット情報が表示され、利用者にとって有益な情報提供が可能になります。
7. パッケージの可視性とアクセス管理
7.1 可視性の設定
パッケージには2つの可視性レベルがあります。
- Public(公開): GitHubの全ユーザーがアクセス可能
- Private(非公開): 指定したユーザーや組織のメンバーのみアクセス可能
重要な点として、一度公開したパッケージを非公開に戻すことはできません。公開前に可視性の設定を慎重に検討する必要があります。
なお、Container registryのパブリックパッケージは特別で、認証なしでの匿名アクセスが可能です。CLIからログインせずにpullできるため、配布が容易になります。
7.2 GitHub Actionsワークフローへのアクセス付与
パッケージを管理するワークフローには、明示的にアクセス権を付与する必要があります。
この設定により、CI/CDパイプライン内でパッケージの公開や更新が自動化できます。
7.3 GitHub Codespacesへのアクセス付与
Codespacesからパッケージにアクセスする場合も、明示的な権限付与が必要です。デフォルトでは、同じリポジトリで公開され、Inherit accessオプションが選択されているパッケージにのみシームレスにアクセスできます。
それ以外のパッケージにアクセスするには、パッケージ設定の「Manage Codespaces access」セクションから、Codespacesを起動するリポジトリを追加します。
これにより、開発環境からプライベートパッケージへの安全なアクセスが実現できます。
7.4 組織レベルでのパッケージ作成可視性設定
組織のオーナーは、メンバーがデフォルトで作成できるパッケージの可視性を制御できます。Granular Permissionsをサポートするレジストリでは、以下の設定が可能です。
- Public: メンバーがパブリックパッケージを作成可能
- Private: メンバーがプライベートパッケージのみ作成可能(組織メンバーのみアクセス可)
- Internal: メンバーがインターナルパッケージを作成可能(エンタープライズの全メンバーがアクセス可)
この設定により、組織全体で一貫したパッケージ管理ポリシーを適用できます。
8. パッケージのライフサイクル管理
8.1 削除の制約
パッケージの削除には以下の制限があります。
- プライベートパッケージ: 全体または特定バージョンを削除可能
- パブリックパッケージ: ダウンロード数が5,000未満の場合のみ削除可能
ダウンロード数が5,000を超えるパブリックパッケージを削除する必要がある場合は、GitHubサポートへの連絡が必要です。
8.2 パッケージの復元
削除したパッケージは、以下の条件を満たせば復元可能です。
- 削除から30日以内
- 同じパッケージ名前空間が利用可能(新しいパッケージで使われていない)
8.3 REST APIによる管理
GitHub Packages REST APIを使用することで、プログラマティックな管理が可能です。
# パッケージバージョンの削除例
curl -X DELETE \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
https://api.github.com/user/packages/container/パッケージ名/versions/バージョンID
Granular Permissionsをサポートするレジストリでは、GitHub Actionsワークフロー内でGITHUB_TOKENを使ってREST API経由での削除や復元も可能です(現在パブリックプレビュー中)。
8.4 GraphQL APIによる削除
Repository-scopedパッケージのプライベートバージョンは、GraphQL APIを使って削除することもできます。
mutation {
deletePackageVersion(input: {
packageVersionId: "MDIyOlJlZ2lzdHJ5UGFja2FnZVZlcnNpb243MTExNg=="
}) {
success
}
}
このAPIを使用する際は、read:packages、delete:packages、repoスコープを持つPersonal Access Token(classic)が必要です。
ただし、Granular Permissionsをサポートするレジストリでは、GraphQL APIは使用できません。これらのレジストリでは、REST APIを使用する必要があります。
9. 料金体系
GitHub Packagesの料金は、パッケージの可視性によって異なります。
9.1 無料枠
- パブリックパッケージ: 完全無料
- プライベートパッケージ: プランに応じた無料ストレージとデータ転送量
9.2 超過料金の制御
無料枠を超える使用量は、予算設定でコントロールできます。有効な支払い方法が登録されていない場合、無料枠を使い切った時点で使用がブロックされます。
支払い方法が登録されている場合でも、予算制限により支出を管理できます。組織やユーザーの設定から、適切な予算を設定することを推奨します。
10. リポジトリの移管とパッケージ
リポジトリを別のユーザーや組織に移管する際、パッケージの扱いはレジストリによって異なります。
10.1 Granular Permissionsの場合
パッケージのスコープは変更されず、元のユーザーや組織に紐付いたままです。リポジトリとの連携は解除されますが、パッケージ自体は移管されません。
10.2 Repository-scopedの場合
パッケージはリポジトリと共に移管されます。課金も新しいオーナーに移行し、以前のオーナーがコラボレーターから外れた場合、パッケージへのアクセスも失われます。
11. まとめ
GitHub Packagesは、ソースコード管理とパッケージ配布を統合し、開発ワークフロー全体を効率化します。重要なポイントは以下の通りです。
-
レジストリごとの権限モデルを理解する: Granular PermissionsとRepository-scopedの違いを把握し、適切な管理方法を選択します
-
認証の自動化: GitHub Actionsで
GITHUB_TOKENを活用することで、トークン管理の負担を軽減できます -
可視性の慎重な設定: 一度公開したパッケージは非公開に戻せないため、公開前に十分な検討が必要です。Container registryのパブリックパッケージは匿名アクセス可能なため、特に注意が必要です
-
アクセス制御の適切な設計: ワークフローやCodespacesへの明示的なアクセス付与により、セキュアな開発環境を構築します
-
削除と復元の制約を理解する: パブリックパッケージのダウンロード数制限や、30日以内の復元期限を考慮します
-
APIの使い分け: Granular PermissionsではREST API、Repository-scopedではREST APIまたはGraphQL APIを使用します
GitHub Packagesを活用することで、パッケージのバージョン管理、アクセス制御、配布の全てをGitHub上で完結させることができます。これにより、開発チームは複数のサービス間を移動する手間から解放され、コードとパッケージの一貫性を保ちながら、より効率的な開発サイクルを実現できます。