Cloud Native Buildpacksとheroku/builder:22でLaravelアプリのコンテナイメージを作成する
こんにちは、ナカエです。
桜の開花とともに初夏のような暖かさがやってきましたね。
弊社ではAWS App Runnerで動かしている社内用のLaravelアプリケーションがあります。
そちらで利用するコンテナイメージのビルドにはCloud Native Buildpacksを用いているのですが、先日ビルダーイメージとして用いていた heroku/buildpacks:20 のサポートが終了している ことに気づきました。
新しいビルダーイメージ heroku/builder:22
を利用する場合は以前の設定を少し変更する必要があり、本記事の内容はそちらの覚書になります。
検証環境とソフトウェアのバージョン
- OS: macOS 14.4.1 (Sonoma)
- CPU: Apple M1 Max
- zsh 5.9
- pack 0.33.2
- PHP 8.3.4(ホストマシン)8.2.2(ビルドするコンテナ)
- Node.js 20.12.2 (ホストマシン・コンテナ双方)
- Laravel 11.0.6
Laravelアプリを作成
下記コマンドで新規Laravelアプリを作成します。
composer create-project laravel/laravel laravel-heroku-builder-22
手元ではLaravel 11.0.6で作成されました。
Cloud Native Buildpacks向けのイメージビルド設定
作成・変更するファイルは 以前のApp Runner + Cloud Native Buildpacksの記事 と同じですが、一部内容が異なります。
Procfile
PHP実行環境の起動について指定するProcfileは変更なしです。nginx + PHP-FPM 構成で動かします。
web: heroku-php-nginx -C nginx.conf public
nginx.conf
locationの設定は同じですが、一時ファイルを保存するのにデフォルトの設定だとApp Runnerのコンテナ起動時にエラーが出たので、/tmp以下に変更しています。
location / {
try_files $uri @rewriteapp;
}
location @rewriteapp {
rewrite ^(.*)$ /index.php$1 last;
}
client_body_temp_path /tmp/client_body_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
project.toml
project.tomlはスキーマをバージョン0.2としているので一部書式が変わっていますが、builderを heroku/builder:22 に変更しているのが主な違いです
[_]
id = "laravel-heroku-builder-22"
name = "Laravel + heroku/builder:22"
version = "1.0.0"
schema-version="0.2"
[io.buildpacks]
builder = "heroku/builder:22"
exclude = [
".idea",
"/README.md",
".git",
"/vendor",
"/node_modules",
"/bootstrap/cache/*.php",
]
[[io.buildpacks.group]]
uri = "heroku/php"
[[io.buildpacks.group]]
uri = "heroku/procfile"
[[io.buildpacks.group]]
uri = "heroku/nodejs"
[[io.buildpacks.build.env]]
name = "NODE_ENV"
value = "production"
composer.json
直接編集すると composer.lock に反映されないので、composerコマンドで設定します。
HerokuのBuildpackはcomposer.jsonを読み込んで自動的にPHP拡張を設定が可能です。 ここではext-pdoとext-pdo_sqliteを指定します。
composer require ext-pdo
composer require ext-pdo_sqlite
差分は下記のようになります
{
// 略
"require": {
"php": "^8.2",
+ "ext-pdo": "*",
+ "ext-pdo_sqlite": "*",
"laravel/framework": "^11.0",
"laravel/tinker": "^2.9"
},
// 略
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
// 略
}
package.json
Node.jsの20系が使えるようになっているのでそちらを指定しています。
{
+ "name": "laravel-heroku-builder-22",
"private": true,
+ "engines": {
+ "node": "20.x"
+ },
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.6.4",
"laravel-vite-plugin": "^1.0",
"vite": "^5.0"
}
}
Node.jsのパッケージマネージャーを決定するのにロックファイルが利用されるため、一度パッケージをインストールしておきます。 pnpmとYarnも選択できますが、今回はnpmを使います。
npm install
パッケージがnode_modulesに配置され、package-lock.jsonが生成されます。
コンテナイメージのビルドとコンテナ実行
pack CLIを使ってビルドします。
まだ導入していない場合はHomeBrewを使ってインストールします。
brew install buildpacks/tap/pack
インストールできたらプロジェクトのルートで下記のコマンドを実行します。
pack build laravel-heroku-builder-22
laravel-heroku-builder-22という名前のコンテナイメージが作成されます。
このイメージを下にコンテナを起動するコマンドが下記です。 ビルドしたコンテナイメージはlinux/amd64向けですが、ホストマシンがM1 Macなのでplatformオプションを明示的に指定しています。
docker run --rm -e PORT=8080 -p 8080:8080 --platform linux/amd64 laravel-heroku-builder-22
http://localhost:8080 にアクセスすると、Laravelのホーム画面が表示されます。
まとめ
一部仕様が変わってはいますが、Herokuのビルダーイメージを使うと相変わらず少ない手数でコンテナイメージが作成できるので重宝しています。ただ、PHP 8.3に早めに対応してもらえるとより嬉しいですね。
- PHP , Laravel , Buildpacks