個人開発したアプリをGCP(GAE)にデプロイするまで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509690/60cc3d5c-e8e0-e68c-21ac-a7667959a415.png)


今回は個人で開発したアプリケーションをGoogle cloud platformの[App Engine](https://cloud.google.com/appengine/?hl=ja&utm_source=google&utm_medium=cpc&utm_campaign=japac-JP-all-ja-dr-bkws-all-super-trial-e-dr-1009137&utm_content=text-ad-none-none-DEV_c-CRE_314712312630-ADGP_Hybrid%20%7C%20AW%20SEM%20%7C%20BKWS%20~%20T1%20%7C%20EXA%20%7C%20Compute%20%7C%201%3A1%20%7C%20JP%20%7C%20ja%20%7C%20app%20engine%20%7C%20app%20engine%20%7C%20en-KWID_43700030995748181-kwd-11351923229&userloc_1009266-network_g&utm_term=KW_app%20engine&gclid=CjwKCAiArIH_BRB2EiwALfbH1I5JqWtKwnAqSQqCceLGsng4N1Cmaz-2owW1H78QqImW_f9yM_I0sRoCerIQAvD_BwE)にデプロイするまでを解説します。


## 前提
解説にあたって、前提があります。

- `React`のアプリをデプロイするので、React寄りの解説になります。(他の言語やフレームワークでもやり方は似ています)
- すでにデプロイするアプリができていること(途中でもOKです)
- アプリ自体の作成については解説しません

上記の前提の上で解説していきます。

## 解説

### 【STEP1】 GCPのアカウント、プロジェクト、GAEの設定
まずは、準備です。
[Google Cloud](https://cloud.google.com/)に登録していない人は、アカウント登録をしましょう。

アカウント登録が済んだらコンソールにログインします。

ログイン後、ダッシュボードのヘッダーの部分にあるロゴの隣にプロジェクトを選択するドロップダウンメニューがあるのでそれを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509690/9dd11c3a-3c00-aa10-f517-28029c05d15d.png)

すでにFirebaseを利用しているなどの場合だと、プロジェクトの一覧部分に該当のプロジェクトがあるかもしれませんが、ない場合は右上の**新しいプロジェクト**からプロジェクトを作成しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509690/8586ae10-9fb6-8749-d918-930b15a9e1f9.png)

### 【STEP2】 SDKをインストール
次に、[Cloud SDK](https://cloud.google.com/sdk/)をインストールします。

インストールに関しては公式の[クイックスタート: Cloud SDK スタートガイド](https://cloud.google.com/sdk/docs/quickstart)がわかりやすいです。

### 【STEP3】 gcloud initを実行する

STEP2で紹介したドキュメントにも書いてありますが、SDKのインストール後、初期化をおこないます。

この初期化では、ユーザーのログインやプロジェクトの選択などを行います。

```console
$gcloud init
```

初期化に関しても公式ドキュメントをご覧ください。
[Cloud SDK の初期化](https://cloud.google.com/sdk/docs/initializing)

#### 地味にハマったポイント
SDKをインストール後、

```console
$gcloud init
```
を実行しようとしたところ、

```console
-bash: gcloud: command not found
```
というエラーが出ました。インストールは完了しているはずなのにと思って調べていると、下記の記事を発見。
[gcloud コマンドが認識されないとき（初心者向け）](https://qiita.com/jre233kei/items/355914b36e505152e29d)

```console
$ cd ~
$ ls -A
```
と打った後に、

```console
$ vi .bash_profile
```

iを押してINSERTモードにし、一番下に以下の2行を追加。

```console 
source <sdkを展開したディレクトリ>/google-cloud-sdk/completion.bash.inc
source <sdkを展開したディレクトリ>/google-cloud-sdk/path.bash.inc
```

ここで、SDKを展開したディレクトリってどこ(??)となるかもしれませんが、もしMacをお使いの場合は、(おそらく)ダウンロードフォルダに入っていると思います。ない場合はfinderの検索機能を使いましょう。(`google-cloud-sdk`と打てば見つかるはずです)
僕の場合はわからなかったので検索して見つけました。
SDKを展開したフォルダを開いて、`completion.bash.inc`と`path.bash.inc`を探し、先ほど開いたbash_profileにドラッグ&ドロップ。

`escキー`を押してINSERTモードから出た後、`:wq`で保存し終了します。

一度、ターミナルを`exit`して再起動。もう一度`gcloud init`を試すと、上手くいきました。

どうやらパスが通っていなかったらしい。。。
パスを通すの意味がイマイチな人は下記の記事を参考にしてみてください。
[「PATH を通す」の意味をできるだけわかりやすく説明する試み](https://qiita.com/sta/items/63e1048025d1830d12fd)

### 【STEP4】 app.yamlファイルを作成する
`app.yaml`ファイルをプロジェクトのルートディレクトリに作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509690/8afd87b4-fe93-0d82-42e7-c88a2b14b36e.png)
(↑プロジェクトルートに`app.yaml`を作成したという図です。)

`app.yaml`では、App Engineのアプリの設定を行います。

GAEは`従量課金制`のため、**スケーリングされればされるほど課金されます。**
なので、個人開発でそんなにアクセスが見込めない場合はあまりスケーリングしないような設定にしておいた方がいいかもしれません。

以下は僕の`app.yaml`ですが、各種設定項目に関しては[公式ドキュメント](https://cloud.google.com/appengine/docs/standard/nodejs/config/appref)を見つつ、**どれがどういう設定項目なのかを理解した上で**、ファイルを記述することをお勧めします。

*※余談ですが、僕はAWSのEC2で設定をミスって(というか全く理解しないまま適当にやって)、10万円請求されたことがあります。なので、オートスケールするようなGCPなどのクラウドサービスを使うときは特に慎重に設定を進めています* 😅

```app.yaml
runtime: nodejs12
env: standard
handlers:
  - url: /static
    static_dir: build/static
  - url: /(.*\.(json|ico|js))$
    static_files: build/\1
    upload: build/.*\.(json|ico|js)$
  - url: .*
    static_files: build/index.html
    upload: build/index.html
    expiration: "0s"
instance_class: F1
automatic_scaling:
  min_idle_instances: automatic
  max_idle_instances: 1
  min_pending_latency: 3000ms
  max_pending_latency: automatic
  max_instances: 1
  min_instances: 0
```
ざっくり説明すると、`runtime`ではnodejs、`env`ではスタンダード環境で実行してくださいという指定を、`handlers`の部分ではbuildフォルダ内ののファイルを使ってくださいという指定をしています。また、オートスケールしないように、`automatic_scaling`の部分で、`max_instances`を１に設定しています。`instance_class`に関しては、[こちらの記事](https://qiita.com/sinmetal/items/017e7aa395ff459fca7c)から引用させていただきます。
>Dialy無料枠はF1:28H, B1:8Hなので、F2やB2などの上のinstance_classを使うと、無料枠の減少が早くなります。
必要最低限のinstance_classを指定すると安くていいです。

つまり、特に必要がなければ無料枠内で使いたい場合、`F1`に設定しておいた方が(無料枠の減りが早くなくて)いいということです。

以下は、`app.yaml`を書く上で参考にした記事です。
[Google App Engine(GAE)を無料枠で収めるための勘所](https://www.serversus.work/topics/p1uaj4jrv8b5x70hwe6p/)
[Create React Appで作成したReactアプリをGoogle App Engineにデプロイする際の設定](https://zenn.dev/h_sakano/articles/c55e22b69cbf989decfa)
[App Engine Scaling Config](https://qiita.com/sinmetal/items/017e7aa395ff459fca7c)

### 【STEP5】 デプロイする
`app.yaml`の設定が終わったら最後はデプロイです。

ですが、その前に`$ npm run build`でもう一度ビルドをしておきます。

ビルドが完了したら以下のコマンドを実行してください。

```console 
$ gcloud app deploy app.yaml --project [project-id]
```

```console 
Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 0 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.                                               
Setting traffic split for service [default]...done.                              
Deployed service [default] to [ここにはURLが表示されます]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse
```

デプロイが上手くいっている場合は上記のようになると思います。
`[ここにはURLが表示されます]`と書いたところに、あなたのアプリケーションのホスト先のURLが書いてあるので、アクセスできるか確認してみましょう。

ちゃんと、想定通りの画面になっていればデプロイ完了です！！

お疲れ様でした🎉

## 最後に
ここまで、`Google App Engine`にアプリをデプロイする方法について解説してきました。

筆者の僕自身、まだクラウドはわからないことだらけで調べつつなんとかデプロイするところまで辿り着きました。ですので、今後App Engineを使う人が少しでも楽できればと思いこの記事を書いています。

また、間違いに気づいたり、今後なんらかのアップデートや`app.yaml`、そしてGCPなどのクラウドに関する知見が溜まったら少しづつ、この記事に書き足していく予定です。

最後までご覧いただきありがとうございました。