今までEC2ばかり使ってきたのですが、そろそろGCPにも仲良くなっておかないといけないなということで、GCPにアプリをLaravelアプリをデプロイしたいと思います。
今回はLaravelアプリの作成方法は割愛させてもらって、すでにローカル環境で動作するLaravelアプリがある前提で進めたいと思います。
ちなみにこの記事を書き始めた時点で筆者はGAEを触ったことがありません。何か間違いがあればどしどし指摘してくれると嬉しいです。
あとローカル環境のPHPとLaravelのバージョンは下記のような感じです。
$ php artisan --version
Laravel Framework 10.3.3
$ php --version
PHP 8.2.6 (cli) (built: May 23 2023 09:42:25) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.6, Copyright (c) Zend Technologies
gcloud CLIのインストール
まずはローカル環境にgcloud CLIをインストールします。すでに導入済みの方は無視してください。
インストールは下記の通りやれば大丈夫でした。
# 事前にインストールしたアーカイブをホームディレクトリに展開する
# インストール
$ ~/google-cloud-sdk/install.sh
# PATHの再読み込み
$ source ~/.zshrc
# このコマンド打てと言われたのでうつ
$ gcloud components update
# バージョン確認
$ gcloud --version
Google Cloud SDK 434.0.0
bq 2.0.93
core 2023.06.02
gcloud-crc32c 1.0.0
gsutil 5.24
インストールが完了したらセットアップも実施しておきましょう
$ gcloud init
App Engineの設定
まずはApp Engineを作成します。GCPのコンソールからApp Engineのアプリケーションを作成します。
EC2に使い慣れてる身からするとインスタンスの選択とかがないので違和感ですが、気にせず次に進みます。
Clousd SQLの設定
次にデータベースです。データベースは今回はCloud SQLを使います。
GCPのコンソールからCloud SQLのインスタンスを作成し、データベースの作成、ユーザーの作成まで実施します。
ちなみにデータベースエンジンは今回はMySQLを選択しました。
ユーザーの作成まで完了したら
- 接続名
- データベース名
- ユーザー名
- ユーザーパスワード
を控えておきます。
app.yamlの作成
GAEにデプロイする時はLaravelプロジェクトルートにapp.yaml
を作成する必要があるようです。
理由は「書き込み可能ディレクトリが/tmpのみしかない」からだそうで、/tmp配下に書き込みするタイプのファイルを置くために必要なんだろうなと思っています。
またenv_variabkes
に指定した値は.env
の値を上書きするようなので、ローカルとデプロイ先の環境変数の違いなどを書いていきます。
runtime: php82
handlers:
- url: /assets
static_dir: public/assets
env_variables:
APP_KEY: YOUR_APP_KEY ## .envのAPP_KEYを記載 例)base64:KVNTvCJvCG~~~
APP_STORAGE: /tmp
VIEW_COMPILED_PATH: /tmp
CACHE_DRIVER: cookie
SESSION_DRIVER: cookie
APP_SERVICES_CACHE: /tmp/services.php
APP_PACKAGES_CACHE: /tmp/packages.php
APP_CONFIG_CACHE: /tmp/config.php
APP_ROUTES_CACHE: /tmp/routes.php
DB_DATABASE: YOUR_DB_DATABASE # データベース名
DB_USERNAME: YOUR_DB_USERNAME # ユーザー名
DB_PASSWORD: YOUR_DB_PASSWORD # パスワード
DB_HOST: "/cloudsql/YOUR_CONNECTION_NAME" # 接続名
ストレージパスの修正
ストレージのパスをapp.yaml
で指定したAPP_STORAGE
になるように、1行追加します。
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
// GCP用に追加
$app->useStoragePath(env('APP_STORAGE', base_path() . '/storage'));
return $app;
.gcloudignoreの作成
.gitignore
のGCP版ですかね。不要なファイルを指定できるようなので、作成します。
/node_modules
/storage/debugbar
/storage/framework/cache/data/*
/storage/debugbar
/storage/logs/*
/vendor/
.env
.github
.git
.gitignore
デプロイ
下記コマンドでデプロイします。
$ gcloud app deploy
Do you want to continue (Y/n)? y
すんなりと行くとよかったのですが、エラーがでてきたので1つ1つ対応していきます。
ERROR: gcloud crashed (FileNotFoundError): [Errno 2] No such file or directory: '~~/public/storage'
Dockerコンテナの中に入ってからphp artisan storage:link
で作成したシンボリックリンクが、コンテナ外だと上手く参照先を見つけれずにエラーになりました。
コンテナ外からコマンドでシンボリックリンクを作成することで解決しました。ただよくよく考えたらそもそもストレージはCloud Storageを使うのでこのシンボリックリンク自体不要なので消してもいいかもしれません。
ERROR: build step 0 "asia.gcr.io/gae-runtimes/utilities/gcs-fetcher:base_XXXXXXXX_XX_XX_XXXX" failed: step exited with non-zero status: 1
Cloud Storageの権限周りでコケてるっぽい?
Cloud Storageに行くとstaging.project.appspot.com
のバケットが作成されていたので、削除して再実行したら解消されました。
Running "composer install --no-dev --no-progress --no-interaction --optimize-autoloader"でエラー
Google App Engineのデプロイ時に動くcomposerのバージョンが2.1.0らしく落ちました。(Laravel10はcomposer2.2以上が必須)
調べたところapp.yaml
に下記を記載することで、デプロイ時のcomposerのバージョンを指定できるらしい。
build_env_variables:
GOOGLE_COMPOSER_VERSION: 2.2.1
というわけでapp.yaml
に上記を追記して再実行することで解消されました。
phpoffice/phpspreadsheet 1.28.0 requires ext-zip * -> it is missing from your system. Install or enable PHP's zip extension.
zip extenstionがないというエラー。 EC2ならapt-get install php8.2-zip
とかで解決しそうですが、GAEの場合そもそもスタンダード環境ではzip拡張機能は使えないようでした。(悲しい)
スタンダード環境だと最小インスタンスが0なのでいいなと思ってたのですが、仕方なくフレキシブル環境とやらに変更することにします。
というわけでapp.yaml
に下記を追記しました。テスト環境なのでそれぞれの値は小さめです。料金も怖いので、、、
runtime: custom # customに変更
env: flex
resources:
cpu: 1
memory_gb: 2
disk_size_gb: 10
automatic_scaling:
min_num_instances: 1
max_num_instances: 2
readiness_check:
path: "/"
またデプロイ時のDockerfileはプロジェクトルートにあるものが参照されるらしいので、プロジェクトルートに移動させました。
Error Response: [7] The App Engine appspot and App Engine flexible environment service accounts must have permissions on the image
dockerイメージをpullするためのStorageオブジェクト閲覧者権限が足りないとのエラーでした。
そこでエラーメッセージ通りオブジェクト閲覧者をIAMでつけたのですが、うまくいかず、、、、
最終的に全部のIAMにストレージ管理者をつけたのですがうまくいきませんでした。。。。
マジか。
今回は諦めた
というわけで今回は諦めました。最終的にデプロイできなくてすみません。
時間がかかりすぎたのもそうですが、スタンダード環境で利用できないことがわかったのも痛手でした。なるべく料金を低く抑えたかったので、大人しくGCEにデプロイし直そうと思います。
エラーの原因はおそらく権限の問題ではなくて、対象のイメージがうまく参照できていなかったのではないかなーと思ったりしていますが、本当のとこは分かりません。単純に僕の理解不足の可能性も大いにあります。
とはいえ今回デプロイしてみて色々と勉強になったことも多かったので、自分の備忘録も兼ねてこの記事は残しました。
今後GAEを触ることがあり、原因を解明できたらまた更新するかもしれません。
最後に本記事を書くにあたって参考にした記事をまとめておきます。
本当はGithub Actionを使った自動デプロイまでやりたかったんだけどな、、、悲しい。実力不足です。出直します。
ありがとうございました!