序論:なぜPHPエコシステムにおけるプライベートパッケージ管理は闇に包まれるのか
Composerの登場により、PHPの依存関係管理は劇的な進化を遂げた。しかし、パブリックなPackagist(packagist.org)の恩恵をそのまま社内ライブラリやプロプライエタリなコードベースに持ち込もうとした瞬間、多くのエンジニアが「認証の壁」と「メタデータ同期の遅延」という名の泥沼に足を踏み入れる。
`composer.json` に `repositories` キーを直書きし、GitのSSH URLを直接指定するアプローチは、チーム規模が5人を超えたあたりから破綻する。依存関係の解決(Dependency Resolution)のたびに各開発者のローカルマシンからリモートGitへ問い合わせが発生し、ネットワークの帯域とタイムアウトの悪夢が始まるのだ。さらに、バージョン制約(SemVer)の解決アルゴリズムが肥大化すると、依存関係の計算だけで数分を消費するようになる。
エンタープライズな開発環境において、社内ライブラリの流通基盤をどう構築するか。選択肢は実質的に2つに絞られる。
1. 自前で静的JSONレポジトリを生成する Satis
2. 完全マネージドなSaaSである Private Packagist
本稿では、単なるツールの使い方比較に留まらず、内部のメタデータキャッシュ構造、メモリ消費の最適化、そしてCI/CDパイプラインおよびDocker環境と完全に統合された自動化スキームの極致を、実務直結のコードとともに解き明かす。
—
1. 内部アーキテクチャの比較:Satis vs Private Packagist
まずは、これら2つのツールが裏側でどのようにデータを保持し、Composerクライアントと通信しているのか、その根幹の仕組み(メカニズム)を暴く。
[ Satis のアーキテクチャ ]
社内Git Repositories ──(CI/CDでビルド)──> Static JSON / Zip files ──(S3/Nginx)──> Composer Client
↑
定期Cronで更新
[ Private Packagist のアーキテクチャ ]
社内Git Repositories ──(Webhook通知)──> Private Packagist Cloud ──(DB/API)──> Composer Client
│
細やかなアクセス制御・監査ログ
Satis:静的ファイルの力技と、その限界
Satis(Composer Satis)は、リポジトリのメタデータを読み込んで、Packagist互換の静的なJSONファイル群を生成するCLIツールだ。
- データフロー: Satisを実行すると、設定されたGitリポジトリをクローンまたはフェッチし、各バージョンの `composer.json` を解析して `packages.json`(あるいは分割されたメタデータファイル)を構築する。これをNginxやAmazon S3などの静的ストレージに配置する。
- メリット: サーバーコストがほぼゼロ。データベースが不要であり、S3の背後にCDNを置けば、数万回のリクエストにも秒速で応答するスケーラビリティを持つ。
- デメリット(致命傷): 動的な更新ができない。ライブラリがプッシュされるたびにSatisのビルド(全リポジトリの走査)を回す必要があり、リポジトリ数が数百を超えるとビルド時間が耐え難い長さになる。また、トークン単位の細かいアクセス制御(「このチームはこのパッケージのこのバージョンだけ見せたい」といった粒度)を実装しようとすると、NginxのBasic認証やリバースプロキシによる複雑なルーティング職人芸が必要になる。
Private Packagist:エコシステムの極みと引き換えのコスト
Private Packagistは、Composerの本家開発チームが提供する商用マネージドサービス(またはオンプレミス版)である。
- データフロー: GitHub/GitLab等のWebhookを受け取り、バックグラウンドワーカーが非同期でメタデータを更新する。Composerクライアントからのリクエストに対しては、OAuthトークンやHTTP Basic認証を検証し、動的にパッケージ情報やZipアーカイブへの署名付きURLを返す。
- メリット: 圧倒的なUX。Webフックによるリアルタイムなメタデータ同期、細やかなACL(アクセスコントロールリスト)、脆弱性アラート(GitHub Advisoryとの統合)、ミラーリング機能(packagist.orgやGitHubからの自動プロキシキャッシュ)。
- デメリット: コスト。チームの人数に比例してライセンス費用が発生する。
—
2. 自前サーバー運用:Satisの極限最適化構成
「コストをかけたくない、あるいは社内ポリシーでクラウドSaaSを使えない」という極限の状況下で、Satisを実用に耐えうるレベルまでチューニングする手法を構築する。
最適化された `satis.json` の設計
デフォルトのSatis設定は、全リポジトリを毎回フルクローンするため重い。パラレル処理とキャッシュを有効化した設定例を示す。
{
“name”: “Acme Corp Private Repository”,
“homepage”: “https://satis.internal.acme.com”,
“repositories”: [
{ “type”: “vcs”, “url”: “git@github.com:acme-corp/auth-sdk.git” },
{ “type”: “vcs”, “url”: “git@github.com:acme-corp/payment-gateway.git” }
],
“require-all”: true,
“archive”: {
“directory”: “dist”,
“format”: “zip”,
“skip-dev”: true
},
“config”: {
“preferred-install”: “dist”
}
}
CI/CD(GitHub Actions)によるインクリメンタル・ビルドの完全自動化
Satisのビルドボトルネックを解消するため、GitHub Actionsを用い、変更があった場合のみ、あるいは定期的にS3へ静的ファイルを同期するパイプラインを構築する。
name: Satis Build Pipeline
on:
schedule:
- cron: ‘/30 ‘ # 30分毎にメタデータを再生成
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Satis Host Repo
uses: actions/checkout@v4
- name: Setup PHP Environment
uses: shivammathur/setup-php@v2
with:
php-version: ‘8.3’
tools: composer:v2
- name: Get Composer Cache Directory
id: composer-cache
run: echo “dir=$(composer config cache-files-dir)” >> $GITHUB_OUTPUT
- name: Cache Composer Dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${