こんにちは!開発現場で日々、コードとインフラの狭間に立ち向かっている皆さん。
突然ですが、こんな経験はありませんか?
「LaravelやSymfony、あるいは独自のPHPアプリケーションを本番サーバーへデプロイしようとした時、`vendor`ディレクトリの転送だけで数万ファイル、数十分もの時間がかかる……」
特にComposerを使ったモダンなPHP開発では、依存パッケージが増えれば増えるほど`vendor/`の中身が肥大化します。Gitで管理しないとはいえ、FTPやrsync、あるいはCI/CDのデプロイメントパイプラインでこの膨大なファイルを毎回転送・同期するのは、ネットワーク帯域の無駄遣いであり、デプロイ時間を引き伸ばす最大のボトルネックです。
今回は、この「vendorディレクトリを丸ごと転送する悪習」を断ち切り、依存関係をひとつの「`.phar`(PHP Archive)」ファイルに凝縮して美しく、爆速でデプロイ・配布する技術を伝授します。
これをマスターすれば、デプロイの速度が劇的に向上するだけでなく、アプリケーションの可搬性が圧倒的に高まりますよ。さあ、一緒にモダンなPHPパッケージングの世界へ足を踏み入れましょう!
—
1. なぜ「vendorディレクトリのデプロイ」は悪手なのか?
まずは、私たちが直面している課題の正体をロジカルに整理しておきましょう。
Composerは、プロジェクトのルートにある`vendor/`ディレクトリにすべての依存ライブラリをダウンロードし、その中に巨大なオートローダー(`autoload.php`)を生成します。
これをそのまま本番環境に持っていくと、以下のような問題が発生します。
- ファイル数の爆発: 数十のライブラリを展開すると、小さなファイルが数万個生成されます。これはOSのinodeを圧迫し、ファイル転送(I/O)において最悪のパフォーマンスを引き起こします。
- セキュリティとノイズ: テストコードやドキュメント、不要な設定ファイル(`.github/`や`tests/`など)まで本番サーバーに混入するリスクがあります。
解決策:すべてを1つの「pharファイル」に閉じ込める
PHPには、JavaのJARファイルやPythonのWheelのように、アプリケーション全体を1つの実行可能なアーカイブファイルにまとめる「Phar(PHP Archive)」という素晴らしい仕様が標準で備わっています。
Composerの依存関係、アプリケーションのソースコード、そして最適化されたオートローダーをすべて「1つの `.phar` ファイル」にコンパイルしてしまう。これが今回目指す「Vendorレス・デプロイ術」です。
—
2. 環境構築と主役ツールの紹介
今回は、PHPのPharビルドを極めてエレガントに行うデファクトスタンダードツール「Humbug Box(通称:Box)」を使用します。
Step 1: Boxのインストール
BoxはグローバルにインストールしてCLIツールとして使います。以下のコマンドを実行してください。
Boxの最新安定版pharを公式リポジトリから取得し、実行権限を付与してパスの通った場所に配置する
curl -s https://box-project.github.io/box/installer | php
sudo mv box.phar /usr/local/bin/box
正常にインストールされたかバージョンを確認
box –version
これで、準備は完了です。
—
3. 実践:HelloWorld的なパッケージング構築
それでは、実際に小さなプロジェクトを作成し、vendorディレクトリを含まない単一のpharファイルを作り上げるまでの流れをハンズオン形式で見ていきましょう。
3-1. プロジェクトの初期化と依存関係のインストール
適当な作業ディレクトリを作成し、Composerの初期設定を行います。今回は依存ライブラリの例として、HTTPクライアントである`guzzlehttp/guzzle`をあえてインストールしてみましょう。
プロジェクト用ディレクトリを作成して移動
mkdir my-app && cd my-app
Composerの初期化(対話なし)
composer init –name=”example/my-app” –type=”project” –no-interaction
依存ライブラリとしてGuzzleを追加
composer require guzzlehttp/guzzle
3-2. アプリケーションコードの作成(HelloWorld)
プロジェクトのルートに、エントリポイントとなる `bin/run` ファイルを作成します。このファイルから、Composerのオートローダーを読み込み、Guzzleを使って外部APIを叩いてみます。
`bin/run`
!/usr/bin/env php
request(‘GET’, ‘https://jsonplaceholder.typicode.com/todos/1’);
echo “API Response Status: ” . $response->getStatusCode() . “\n”;
echo “API Response Body: ” . $response->getBody() . “\n”;
} catch (\Exception $e) {
echo “Error: ” . $e->getMessage() . “\n”;
}
作成したら、ローカルで実行できるか確認します。
chmod +x bin/run
./bin/run
無事にJSONレスポンスが表示されれば、ベースのコードは完璧です。
—
4. Boxを設定し、すべてを1つのPharに凝縮する
ここからが本番です。Boxに「どのファイルをまとめ、どのように圧縮するか」を教えるための設定ファイル `box.json` をプロジェクトのルートに作成します。
`box.json`
{
“chmod”: “0755”,
“directories”: [
“bin”,
“vendor”
],
“main”: “bin/run”,
“output”: “my-app.phar”,
“compactors”: [
“Humbug\\Box\\Compactor\\PhpComposer”
],
“stub”: true
}
設定値の深い解説
- `”directories”: [“bin”, “vendor”]`: アーカイブに含めるディレクトリを指定します。ここに`vendor`をあらかじめビルドした状態で含めます。
- `”main”: “bin/run”`: Pharを実行した際に最初に呼び出されるエントリポイントを指定します。
- `”output”: “my-app.phar”`: 生成される成果物のファイル名です。
- `”compactors”: […]`: PHPコードからコメントや空白を自動で削除し、ファイルサイズを軽量化するコンパイル設定です。
- `”stub”: true`: このファイルを直接 `./my-app.phar` として実行できるようにPHPの実行ヘッダー(Stub)を自動生成します。
—
5. ビルド実行と動作確認
設定ファイルができたら、いよいよBoxを使ってパッケージングを行います。
Boxにビルドを指示
box compile
ビルドが成功すると、プロジェクトのルートディレクトリに `my-app.phar` という単一のファイルが生成されます!
ディレクトリサイズを比較してみる
ここで、従来のやり方と今回のやり方でどれほどの差が出たか確認してみましょう。
vendorディレクトリのサイズを確認
du -sh vendor/
生成されたpharファイルのサイズを確認
du -sh my-app.phar
環境にもよりますが、`vendor/`直下にある数千〜数万のファイルが、たった1つの軽量な`.phar`ファイル(数メガバイト程度)に圧縮されていることに気づくはずです。
Pharの実行テスト
なんと、この `my-app.phar` は、`vendor`ディレクトリが一切存在しない別の場所にコピーしても、単体で完璧に動作します。
適当な別ディレクトリへ移動してみる
cd /tmp
先ほどビルドしたpharファイルをコピー(パスは環境に合わせて調整してください)
cp /path/to/my-app/my-app.phar .
vendorディレクトリが無い状態で実行!
./my-app.phar
見事に先ほどと同じAPIレスポンスが返ってきたはずです。
—
6. 現場のアーキテクトが教える、さらなる運用ティップス
このPhar化デプロイを実際のCI/CD(GitHub ActionsやGitLab CIなど)に組み込む際は、以下のフローを組むと最強です。
1. Checkout: リポジトリのソースコードを取得する(この時点ではvendorはない)。
2. Composer Install: `composer install –no-dev –optimize-autoloader` で本番用の軽量な依存関係を入れる。
3. Box Compile: `box compile` で `my-app.phar` を生成する。
4. Deploy: 生成された `my-app.phar` のみを本番サーバーへ転送する。
本番サーバー側では、PHPさえ入っていれば `php my-app.phar` あるいは `./my-app.phar` を叩くだけでアプリケーションが稼働します。転送ファイル数は「たった1つ」になり、デプロイ時間は劇的に短縮されます。
—
おわりに
今回は、Composerの`vendor`ディレクトリに依存した非効率なデプロイから脱却し、Boxを用いたPhar化によって単一ファイルでアプリケーションを配布する手法を解説しました。
「ファイルをそのまま置く」というPHPの気軽さの良さを残しつつ、エンタープライズなビルド&パッケージングの思想を取り入れることで、あなたの開発環境やデプロイパイプラインは一段上のステージへと進化します。
これをマスターすれば、毎日のデプロイ待ち時間がストレスになることはもうありませんよ。ぜひ、次のプロジェクトのデプロイフローに導入してみてください!