こんにちは!日々の開発、本当にお疲れ様です。
皆さんはPHPのパッケージ管理ツール「Composer」を普段どのように使っていますか? `composer install` や `composer update` を実行し、ライブラリをサクッと落としてくる――それだけでも十分便利ですよね。
しかし、Composerの本領は、グローバル設定ファイルである `config.json` をハックした瞬間から本当の意味で発揮されます。特にローカル開発環境のパフォーマンスを極限まで高めたり、特殊な権限管理が求められる環境でエラーを完全に回避したりするには、デフォルトの挙動を知り尽くし、適切にチューニングすることが不可欠です。
今回は、公式ドキュメントの隅っこにひっそりと書かれている、しかし実務では「これを知っているかどうかで開発ストレスが10倍変わる」隠し味的な設定、`cache-files-maxsize` と `cache-read-only` に焦点を当てます。
これをマスターすれば、あなたのマシンのディスク容量が謎のキャッシュで圧迫されることも、共有サーバーで突然権限エラーに悩まされることもなくなりますよ。さあ、一緒にComposerの裏側を覗いてみましょう!
—
1. そもそもComposerの「キャッシュ」って中でどう動いているの?
設定の話に入る前に、Composerが内部でどのようにデータを扱っているかを知る必要があります。
Composerは、遠く離れたPackagistやGitHubからZIPファイルをダウンロードしてきます。しかし、同じバージョンのライブラリを何度もダウンロードするのはネットワークの無駄ですし、何より遅いですよね。そのため、Composerは一度取得したZIPファイルをローカルのマシン(通常は `~/.cache/composer` や `C:\Users\
このキャッシュのおかげで、2回目以降のインストールは爆速になります。しかし、ここで2つの大きな問題が生まれます。
1. ディスク容量の無駄遣い: 長期間開発していると、使わなくなった古いライブラリのZIPが溜まりに溜まり、気づけば数十GBを消費している。
2. 権限(Permission)の衝突: Dockerコンテナ、WSL2、ホストOS間でボリュームを共有したり、複数人で1台の共有サーバーを触ったりすると、キャッシュファイルの所有者権限が狂い、`Permission denied` エラーの温床になる。
この問題を鮮やかに解決するのが、今回紹介する2つの設定です。
—
2. インストールから基礎セットアップまでのおさらい
本題に入る前に、そもそもComposerが手元にない、あるいは基礎を固めたいという方のために、最短かつ最も堅牢なセットアップ手順を確認しておきましょう。すでに導入済みの方は読み飛ばして構いません。
公式インストーラーによる安全な導入
Composerは単なるPHPスクリプトです。グローバルに安全に配置するためには、公式のインストーラーをPHPで直接実行するのが最も確実です。
1. インストーラーをカレントディレクトリにダウンロード
php -r “copy(‘https://getcomposer.org/installer’, ‘composer-setup.php’);”
2. 公式のSHA-384ハッシュと突合して改ざんがいないか検証(セキュリティの基本!)
※最新のハッシュ値は公式サイト(https://getcomposer.org/download/)を確認してください
php -r “if (hash_file(‘sha384’, ‘composer-setup.php’) === ‘e21205b207c3ff031906541ff12216dcb067353bef78c474cad161429d32f643db026d178fcdc2d7cbb52150bab760d7’) { echo ‘Installer verified’; } else { echo ‘Installer corrupt’; unlink(‘composer-setup.php’); } echo PHP_EOL;”
3. インストーラーを実行して composer.phar を生成
php composer-setup.php
4. インストーラー本体を削除
php -r “unlink(‘composer-setup.php’);”
5. システム全体(パスが通った場所)へ ‘composer’ という名前で移動
sudo mv composer.phar /usr/local/bin/composer
動作確認(Hello World的アプローチ)
正しくインストールされたか確認しつつ、Composerの挙動を体感するために、適当な空ディレクトリで最小限のプロジェクトを作ってみましょう。
作業用ディレクトリを作成して移動
mkdir composer-lab && cd composer-lab
最小限の依存関係(例: ログ出力ライブラリ monolog)を対話なしで要求する
composer require monolog/monolog
実行すると、`vendor/` ディレクトリと `composer.json`、そして `composer.lock` が生成されます。これがComposerの基本的な世界です。
—
3. 実務で効く!`config.json` の魔改造テクニック
ここからが本番です。Composerのグローバル設定ファイル(通常は `~/.config/composer/config.json` または Windowsの `%APPDATA%\Composer\config.json`)を直接編集し、ローカル開発環境をハックします。
設定ファイルの全体像は以下のようになります。
{
“config”: {
“cache-files-maxsize”: “1GiB”,
“cache-read-only”: false
}
}
この2つの設定が、現場のエンジニアにどのような救いをもたらすのか、詳しく解説していきます。
—
その1:`cache-files-maxsize` でディスク肥大化を防ぐ
これは何をする設定か?
Composerが保持するZIPファイルのキャッシュ総容量(上限)を指定する設定です。デフォルトでは、なんと `7GiB` もの大容量が割り当てられています。
なぜこの設定が必要なのか?
「7GBもあれば安心じゃないか」と思われるかもしれません。しかし、近年のモダンなPHPフレームワークや豊富なパッケージエコシステムにおいて、長年さまざまな案件を行ったり来たりしていると、気がつけばローカルのSSDがパンパンになります。特にノートPCで容量の少ないSSD(256GBや512GBモデル)を使っている開発者にとって、Composerが勝手に数ギガバイトを占有し続けるのは死活問題です。
また、CI/CDのコンテナ環境やDockerイメージのビルド時においても、不要に大きなキャッシュが含まれるとイメージサイズが膨らみ、デプロイ速度の低下を招きます。
実践:容量を絞る
グローバル設定に以下を追記し、上限を「1ギガバイト」に制限してみましょう。
{
“config”: {
“cache-files-maxsize”: “1GiB”
}
}
※単位には `k` (KB), `M` (MB), `G` (GB) のほか、`KiB`, `MiB`, `GiB` が使えます。
これを行うと、Composerは定期的なクリーンアップや新規キャッシュ保存時に自動的に容量を計算し、古い(アクセス頻度の低い)キャッシュからパージ(削除)してくれます。ディスク容量を常にクリーンに保てるため、「あ、Macの容量足りない……」という絶望的な通知から解放されます。
—
その2:`cache-read-only` で共有サーバー・Dockerの権限地獄を断つ
これは何をする設定か?
Composerがキャッシュディレクトリへ書き込みを行うかどうかを制御するフラグです。`true` に設定すると、キャッシュディレクトリを完全な読み取り専用として扱います。
なぜこの設定が必要なのか?
これが今回の最も深い知見です。
次のような開発・運用構成をとっている現場はないでしょうか?
- Dockerコンテナ内で、ホストマシンのディレクトリをマウントしてComposerを実行している。
- 複数の開発者がアクセスする共有開発サーバー、あるいはWebホスティング環境でデプロイ作業をしている。
このような環境では、「誰がどのUID/GID(ユーザーID/グループID)でファイルを生成したか」という権限問題が常に牙を向きます。
例えば、Docker内の `www-data` ユーザー(UID: 33)がComposerキャッシュを生成したあと、ホスト側のローカルユーザー(UID: 1000)で同じキャッシュにアクセスしようとすると、有名なあのエラーが起きます。
> `[RuntimeException] Could not scan for files under /home/user/.cache/composer/…`
> `Permission denied`
この権限エラーに直面するたびに `sudo chown -R …` を叩いているとしたら、時間の大いなる無駄です。
実践:キャッシュを「読み取り専用」として割り切る
もしその環境が「キャッシュを作る側(CIや専用の管理者)」と「使う側(各開発者やデプロイ先)」に分かれている場合、あるいはDocker等で毎回クリーンな状態でビルドするのであれば、キャッシュへの書き込み自体を禁止してしまうのが最もスマートです。
{
“config”: {
“cache-read-only”: true
}
}
この設定の妙味:
これを `true` にすると、Composerは「おっ、キャッシュディレクトリに書き込みにいかなくていいんだな」と判断するため、ファイル権限の競合や `Permission denied` エラーが構造的に一切発生しなくなります。
もちろん、書き込まないということは新規のZIPキャッシュはローカルに残りませんが、既存のキャッシュを読むだけの環境(あるいはあらかじめ共有されたマスターキャッシュを読む環境)であれば、パフォーマンスを落とさず、かつ権限トラブルを完全にハック(無効化)することができるのです。
—
4. 設定の反映と動作確認
設定ファイル(`~/.config/composer/config.json`)を書き換えたら、正しく認識されているかをコマンドで確認してみましょう。
ターミナルで以下のコマンドを実行してください。
composer config –global –list
出力結果の中に、先ほど設定した値が反映されているはずです。
[config.cache-files-maxsize] 1GiB
[config.cache-read-only] 1
もし特定のプロジェクトだけでこの挙動をテストしたい場合は、グローバルの `–global` を外し、プロジェクト直下の `composer.json` の中に直接 `config` ブロックを記述することも可能です。
{
“name”: “my-project/app”,
“require”: {
“monolog/monolog”: “^3.0”
},
“config”: {
“cache-files-maxsize”: “500MiB”,
“cache-read-only”: false
}
}
実際に `composer update -vvv`(詳細ログモード)などで実行してみると、キャッシュの読み込み挙動が変化している様子がログから読み取れるはずです。
—
ドキュメントの表面をなぞるだけでは決して見えてこない、Composerの内部キャッシュのメカニズムと、それを手なずけるための `cache-files-maxsize`、`cache-read-only` の活用法。いかがでしたでしょうか?
こうした細かな開発環境のボトルネックやストレスの芽を一つずつ摘んでいくことこそが、一流のエンジニアへの確実な一歩であり、日々のコーディングを極限まで快適にする秘訣です。
ぜひ、あなたの手元の開発環境やチームのDocker構成にも取り入れて、その快適さを実感してみてください。あなたの開発ライフがより一層素晴らしいものになることを応援しています!