Laravel10アプリを初めてGoogle App Engine(GAE)にデプロイしてみて最後の最後でできなかった話


今までEC2ばかり使ってきたのですが、そろそろGCPにも仲良くなっておかないといけないなということで、GCPにアプリをLaravelアプリをデプロイしたいと思います。

今回はLaravelアプリの作成方法は割愛させてもらって、すでにローカル環境で動作するLaravelアプリがある前提で進めたいと思います。

ちなみにこの記事を書き始めた時点で筆者はGAEを触ったことがありません。何か間違いがあればどしどし指摘してくれると嬉しいです。

あとローカル環境のPHPとLaravelのバージョンは下記のような感じです。

```shell
$ 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をインストールします。すでに導入済みの方は無視してください。

インストールは下記の通りやれば大丈夫でした。

https://cloud.google.com/sdk/docs/install?hl=ja#linux


```zsh
# 事前にインストールしたアーカイブをホームディレクトリに展開する
# インストール
$ ~/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
```

インストールが完了したらセットアップも実施しておきましょう

```zsh
$ gcloud init
```

## App Engineの設定

まずはApp Engineを作成します。GCPのコンソールからApp Engineのアプリケーションを作成します。

![スクリーンショット 2023-06-07 11.34.01（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724713/db588ff8-b994-1621-b353-efe16c03537b.png)

EC2に使い慣れてる身からするとインスタンスの選択とかがないので違和感ですが、気にせず次に進みます。


## Clousd SQLの設定

次にデータベースです。データベースは今回はCloud SQLを使います。

GCPのコンソールからCloud SQLのインスタンスを作成し、データベースの作成、ユーザーの作成まで実施します。

ちなみにデータベースエンジンは今回はMySQLを選択しました。

![スクリーンショット 2023-06-07 11.39.13（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724713/41c9d45e-df47-6c7b-0245-de29807e4e4f.png)


ユーザーの作成まで完了したら

 - 接続名
 - データベース名
 - ユーザー名
 - ユーザーパスワード
 
を控えておきます。


## app.yamlの作成

GAEにデプロイする時はLaravelプロジェクトルートに`app.yaml`を作成する必要があるようです。
理由は「書き込み可能ディレクトリが/tmpのみしかない」からだそうで、/tmp配下に書き込みするタイプのファイルを置くために必要なんだろうなと思っています。

また`env_variabkes`に指定した値は`.env`の値を上書きするようなので、ローカルとデプロイ先の環境変数の違いなどを書いていきます。

```yaml:app.yaml
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行追加します。


```php:bootstrap/app.php
/*
|--------------------------------------------------------------------------
| 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版ですかね。不要なファイルを指定できるようなので、作成します。

```:.gcloudignore
/node_modules
/storage/debugbar
/storage/framework/cache/data/*
/storage/debugbar
/storage/logs/*
/vendor/
.env
.github
.git
.gitignore
```




## デプロイ

下記コマンドでデプロイします。

```zsh
$ 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らしく落ちました。（Laravel１０はcomposer2.2以上が必須）

調べたところ`app.yaml`に下記を記載することで、デプロイ時のcomposerのバージョンを指定できるらしい。

```yaml:app.yaml
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`に下記を追記しました。テスト環境なのでそれぞれの値は小さめです。料金も怖いので、、、

```yaml: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: "/"
```

https://cloud.google.com/appengine/docs/flexible/custom-runtimes/configuring-your-app-with-app-yaml?hl=ja

またデプロイ時の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を触ることがあり、原因を解明できたらまた更新するかもしれません。

最後に本記事を書くにあたって参考にした記事をまとめておきます。


https://qiita.com/kazuhideoki/items/0590cf30206831627d39

https://qiita.com/ku_suke/items/0b142fffd22be12d8b6b

https://qiita.com/Baisel/items/2280aefb2727d9690444

https://software.satoshis.jp/?p=379

https://qiita.com/kazuhideoki/items/0590cf30206831627d39

https://zenn.dev/mkhana/articles/2af30ee01f6af5

https://zenn.dev/catnose99/articles/f99ea2a8b985b2


本当はGithub Actionを使った自動デプロイまでやりたかったんだけどな、、、悲しい。実力不足です。出直します。

ありがとうございました！