PHP対応したGoogle Cloud's BuildpacksでLaravelアプリのコンテナイメージをビルドしてCloud Runにデプロイする
こんにちは、ナカエです。
今回は 以前の記事 で紹介した Cloud Native Buildpacks を活用するシリーズの続きです。
Google Cloud’s Buildpacks(日本語訳: Google CloudのBuildpack) がいつの間にやらPHPをサポートしていたので、こちらを使ってLaravelアプリをサクッとCloud Runにデプロイするというになります。
今まではPHPアプリをCloud Runにデプロイするには
- 自前のDockerfileを書く
- Cloud Native Buildpacksを利用したコンテナイメージのビルドのために自前でCloud Buildを設定する
などの必要性がありました。
参考: Cloud Native BuildpacksでビルドしたLaravelアプリのイメージをCloud Runにデプロイする
後者をGoogle CloudのBuildpackの仕組みで置き換えることができるので非常に楽になりましたよ、という話になります。
検証環境とソフトウェアのバージョン
- OS: macOS Ventura 13.4
- CPU: Apple M1 Max
- zsh 5.9
- GNU bash 3.2.57
- PHP 8.2.0
- Composer 2.5.8
- Laravel 10.2.3
Google CloudのBuildpack
Google Cloudでは、 Google Cloud’s Buildpacks としてCloud Native Buildpacksに準拠した仕組みを備えており、コンテナイメージの自動生成が可能です。
言語は
- Python
- Node.js
- Java
- Go
- Ruby
- PHP
- .NET Core
に対応しています。
サポートされているバージョンについて詳しくはドキュメントの ビルダー | Buildpacks | Google Cloud をご覧ください。
Cloud Runなど向けの汎用ビルダーのPHP対応はいつの間にか行われていましたが、割と最近です。
ちなみにGoogle App EngineとCloud Functionsも同じくGoogle Cloud’s Buildpacksのビルダーを活用されています。特にApp Engineの第2世代ランタイム向けに使われるビルダーは、App Engine特有の設定が追加されています。
ビルダーのドキュメントに記載されている gcr.io/buildpacks/builder:v1
などのGoogle Cloud’s Buildpacksが用意しているビルダーを指定することで、ローカルでもpackコマンドでコンテナイメージをビルドし、Google Cloudで動くコンテナイメージと同じものの内容を確認することができます。
今回の記事も、ローカルでビルドしたコンテナイメージを調べて試行錯誤した成果です。
Laravelアプリを作成
まずはComposerを使ってLaravelアプリを作成します。
参考: Installation - Laravel - The PHP Framework For Web Artisans のページの #Your First Laravel Project
作業用のディレクトリに移動し下記コマンドを打つとセットアップが始まります。
composer create-project laravel/laravel laravel-google-clouds-buildpacks
この状態で一度Gitコミットしておきます。
git init
git add .
git commit -m "first commit"
git branch -M main
Google Cloud’s Buildpack向けのビルド設定
Laraelプロジェクトに直下で引き続き作業します。
以前のCloud Native Buildpacksの記事 ではHerokuのBuildpackを利用していましたが、今回はGoogle Cloud’s Buildpackのビルダー gcr.io/buildpacks/builder:v1
を利用します。
設定ファイルを作成・追記していきます。
Procfile
web: pid1 --nginxBinaryPath nginx --nginxConfigPath /layers/google.php.webconfig/webconfig/nginx.conf --serverConfigPath /workspace/nginxserver.conf --nginxErrLogFilePath /layers/google.php.webconfig/webconfig/nginx.log --customAppCmd "php-fpm -R --nodaemonize --fpm-config /layers/google.php.webconfig/webconfig/php-fpm.conf" --pid1LogFilePath /layers/google.php.webconfig/webconfig/pid1.log --mimeTypesPath /layers/google.utils.nginx/nginx/conf/mime.types --customAppSocket /layers/google.php.webconfig/webconfig/app.sock
コンテナのエントリポイントとなるコマンドを指定するファイルです。 pid1
という実行ファイルからnginxとPHP-FPMを起動するようになっています。オプションがとても長いです。
nginxserver.conf
fastcgi_read_timeout 24h;
# proxy_* are not set for PHP because fastcgi is used.
upstream fast_cgi_app {
server unix:/layers/google.php.webconfig/webconfig/app.sock fail_timeout=0;
}
server {
listen 8080 default_server;
listen [::]:8080 default_server;
server_name "";
root /workspace/public;
rewrite ^/(.*)$ /index.php$uri;
location ~ ^/index.php {
error_log stderr;
fastcgi_pass fast_cgi_app;
fastcgi_buffering off;
fastcgi_request_buffering off;
fastcgi_cache off;
fastcgi_store off;
fastcgi_intercept_errors off;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
if ($http_x_forwarded_proto = 'https') {
set $https_setting 'on';
}
fastcgi_param HTTPS $https_setting if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param REMOTE_HOST $remote_addr;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param X_FORWARDED_FOR $proxy_add_x_forwarded_for;
fastcgi_param X_FORWARDED_HOST $http_x_forwarded_host;
fastcgi_param X_FORWARDED_PROTO $http_x_forwarded_proto;
fastcgi_param FORWARDED $http_forwarded;
}
}
HerokuのBuildpackと比べるとnginxの設定ファイルも若干長めですね。ドキュメントルートを変えたかっただけなのですが。
project.toml
[_]
id = "my-project"
name = "My Project"
version = "1.0.0"
schema-version="0.2"
[io.buildpacks]
builder = "gcr.io/buildpacks/builder:v1"
exclude = [
".idea",
"/README.md",
".git",
"/vendor",
"/node_modules",
"/bootstrap/cache/*.php",
]
[[io.buildpacks.group]]
uri = "google.nodejs.runtime"
[[io.buildpacks.group]]
uri = "google.nodejs.npm"
[[io.buildpacks.group]]
uri = "google.php.runtime"
[[io.buildpacks.group]]
uri = "google.php.composer-install"
[[io.buildpacks.group]]
uri = "google.php.composer"
[[io.buildpacks.group]]
uri = "google.php.webconfig"
[[io.buildpacks.group]]
uri = "google.utils.nginx"
[[io.buildpacks.group]]
uri = "google.config.entrypoint"
[[io.buildpacks.group]]
uri = "google.utils.label-image"
[[io.buildpacks.build.env]]
name = "GOOGLE_COMPOSER_VERSION"
value = "2.5.8"
project.tomlの書式(スキーマ)はバージョン0.2としています。 Google CloudのビルダーはHerokuより機能の粒度が細かい印象ですね。
composer.json
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
- "php": "^8.1",
+ "php": "~8.2.0",
+ "ext-grpc": "*",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8"
},
// 略
PHPのバージョンを8.2系に指定し、HerokuのBuildpackでは扱いづらかったext-grpcを試しに追加します。
追記したらcomposer.lockを最新にしておきます。
composer update --ignore-platform-reqs
Herokuのようにcomposer.jsonのrequireにバージョン指定しただけではPHP拡張は有効にはならないので、下記のphp.iniの設定も必要です。
php.ini
[opcache]
zend_extension=opcache
opcache.enable=1
[grpc]
extension=grpc.so
; PHP extension files in gcr.io/buildpacks/builder:v1
; grpc.so
; imagick.so
; mailparse.so
; memcached.so
; mongodb.so
; opcache.so
; opencensus.so
; protobuf.so
; redis.so
gRPC拡張の有効化に加え、デフォルトではOPcacheが無効だったので有効化しています。gcr.io/buildpacks/builder:v1
のビルダーでサポートされている(というよりはsoファイルの存在を確認した)PHP拡張は上記ファイル下部のコメントの一覧のとおりです。
なお、次期バージョンのビルダー gcr.io/buildpacks/builder:google-22
はPHP拡張がほとんどサポートされていないようでした。
package.json
{
"private": true,
"type": "module",
+ "engines": {
+ "node": "18.x"
+ },
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"vite": "^4.0.0"
}
}
enginesの設定を追記してNode.jsのバージョンを18系に指定しています。
GitHubのリポジトリにPush
ここまでのローカルのLaravelプロジェクトの変更をコミットしてリモートにpushします。
{GITHUB_ACCOUNT}/laravel-google-clouds-buildpacks
という名前で GitHubリポジトリを作成します。
※ {GITHUB_ACCOUNT} は適宜置換してください。
git add .
git commit -m "build configuration"
git remote add origin https://github.com/{GITHUB_ACCOUNT}/laravel-google-clouds-buildpacks.git
git push -u origin main
Google Cloud の設定とデプロイ
続いて本命のGoogle Cloudの設定です。
Google Cloud Consoleから laravel-google-cloud-buildpack という名前でプロジェクトを作成します 。
プロジェクトの作成が完了したら、Cloud Runのページにアクセスしましょう。
「サービスを作成」 ボタンをクリックしてサービス作成画面に遷移します。 この際、自動的にCloud Run Admin APIが有効化されます。
「ソース リポジトリから新しいリビジョンを継続的にデプロイする」を選択肢、「CLOUD BUILD の設定」ボタンをクリックします。
右サイドにCloud Buildの設定が開くので、ソースリポジトリ としてリポジトリ プロバイダはGitHubを選択し、リポジトリを選択します。
GitHubのアカウントでGoogle Cloud Buildのアプリをインストールしたことがない場合は「Google Cloud Build のインストール」ボタンが表示されているのでこちらをクリックし、案内に従ってリポジトリを追加できます。 Only select repositoriesを選択してCloud Buildが接続できるリポジトリを絞るほうがおすすめです。
すでにGoogle Cloud BuildのGitHubアプリをインストール済みで設定したいリポジトリが見つからない場合は、「接続されたリポジトリを管理します」というリンクをクリックすることでGoogle Cloud Buildが参照できるリポジトリを追加しましょう。
リポジトリを新規に追加した後に、注意事項への同意のチェックが必要です。
「次へ」 ボタンをクリックして ビルド構成 に進みます。
ビルドタイプ として 「Go、Node.js、Python、Java、.NET Core、Ruby、PHP(Google Cloud の Buildpacks を使用)」を選択します。ほかはデフォルトのままでOKです。
「保存」をクリックするとCloud Buildの設定は完了し、Cloud Runのサービス作成画面に戻ります。
表示されている項目を下記のとおり設定してください。
- サービス名: laravel-google-cloud-buildpack
- リージョン: asia-northeasat1 (東京)
- 自動スケーリング インスタンスの最大数 1
- 認証: 未認証の呼び出しを許可
続けて「コンテナ、ネットワーキング、セキュリティ」を展開し、コンテナの環境変数を設定します。
APP_KEYはローカル環境で生成されているはずなので.envのAPP_KEYの値をコピー&ペーストしてください。また、LOG_CHANNELの値をstderrにして、標準出力にログが出力されるようにしておくとデバッグしやすくなります。
他はデフォルトのままで「作成」をクリックします。
本体であるCloud Runのサービスに加え、Cloud BuildのトリガーやArtifact Registryのコンテナイメージ用リポジトリなどが自動で作成されます。
作成した laravel-google-cloud-buildpack のサービスの詳細ページに移り、初 期設定と初回のデプロイが開始されます。
デプロイが完了するまで2〜3分程かかるのでしばらく待ちます。
Cloud Runのサービスの詳細の上部に表示されているURLをクリックしするとデプロイされたアプリケーションにアクセスできます。
まとめ
Google Cloud’s Buildpacksを利用してLaravelアプリケーションをCloud Runにデプロイする仕組みを構築しました。
用意する設定ファイルは少し多いものの、以前より遥かに簡単になりましたね。
この記事もPHPerのGoogle Cloud/Cloud Run利用が広がる一助となれば幸いです。
- Laravel , GCP , Buildpacks , Cloud Run