SpringBootアプリをGAE/FE(Custom Runtime)にCloud Buildを使ってデプロイする

# はじめに
[前回の記事](https://qiita.com/items/36b63fd053e383807056) では SpringBootアプリ を GAE/FE(Custom Runtime) にローカルから
デプロイしてみましたが、今回はこれを [Cloud Build](https://cloud.google.com/cloud-build/?hl=ja) を使って自動化します。

前提として *前回のデプロイが成功する状態* になっているものとします。

# Cloud Build の仕組み

[Cloud Build](https://cloud.google.com/cloud-build/docs/overview?hl=ja) はコンテナを動かす VM を提供してくれます。

開発者が次の３点を用意すると VM でコンテナを起動し、
指定した順にコマンドを実行してくれます。

- [GAEにデプロイするアプリのソース](https://github.com/tnagao3000/deploy-springboot-webapp-to-gae-fe-custom-using-cloud-build-and-kms/tree/deploy-springboot-webapp-to-gae-fe-custom)
- Build に使うツールの詰まったコンテナイメージ
- Build の手順を記載したビルド構成ファイル (cloudbuild.yaml)

※ コンテナで出来ることであれば、デプロイ以外の処理でも良さそうです。

# 事前準備

後々必要になるため次の３点について事前に対応しておきます。

- Cloud Build API を有効にする
- App Engine Admin API を有効にする
- Cloud Build（のサービスアカウント）に App Engine の操作権限を付与する

### Cloud Build API を有効にする
下図の通り、[公式のこちら](https://cloud.google.com/cloud-build/docs/quickstart-docker?hl=ja#before-you-begin) に記載されている手順で Cloud Build API を有効にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/80c42e07-ef68-477a-7177-c46f1ac26805.png)

WEBコンソールに移動したら、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/31946390-0187-c89c-077a-71564afcd980.png)

### App Engine Admin API を有効にする
下図の通り、[公式に記載されているリンク](https://cloud.google.com/cloud-build/docs/configuring-builds/build-test-deploy-artifacts?hl=ja#deploying_artifacts) から API を有効にします。
※ 認証情報の取得は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/d0fdbc6c-3ac6-b8e5-cae1-ad7ce626dc9e.png)


### Cloud Build に App Engine の操作権限を付与する
上記スクショの 2. の方法で App Engine をいじれるよう Cloud Build に追加の権限を付与します。
次の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/10ac946f-2b0c-3500-3c65-6d6d09d7ccbf.png)

編集画面で役割を追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/b2740d5e-4c39-41c2-4976-38d47ef13451.png)

以上で事前準備は完了です。

# ソースを修正する

冒頭で少し触れましたが、次の２つのファイルを追加で用意します。

- Build に使うツールの詰まったコンテナイメージ（を作るためのDockerfile）
- Build の手順を記載したビルド構成ファイル (cloudbuild.yaml)

上記を追加済みの [ソースはこちら](https://github.com/tnagao3000/deploy-springboot-webapp-to-gae-fe-custom-using-cloud-build-and-kms/tree/deploy-springboot-webapp-to-gae-fe-custom-using-cloud-build) です。

### Build に使うツールの詰まったコンテナイメージ（を作るためのDockerfile）を追加する

Build に使うツールの詰まったコンテナイメージは、
よく使いそうなものについては公式が [用意しています](https://cloud.google.com/cloud-build/docs/cloud-builders?hl=ja) 。

上記で事足りる場合は自分でイメージを作る必要はありません。

今回は `jdk` と `maven` と `gcloud` の入っているイメージが欲しかったのですが、
公式に全部入りのものが無かったため、カスタムイメージを作ります。

カスタムイメージ（ビルドステップ）について [公式の解説はここ](https://cloud.google.com/cloud-build/docs/create-custom-build-steps?hl=ja) にあります。
作成した Dockerfile は次の通りです。

```docker:Dockerfile.gcloud-maven
FROM gcr.io/cloud-builders/gcloud

RUN apt-get update && apt-get install openjdk-8-jdk -y && apt install maven -y

ENTRYPOINT []
```

この Dockerfile からコンテナイメージを作成する処理は次項 (cloudbuild.yaml内) で指定します。

### Build の手順を記載したビルド構成ファイル (cloudbuild.yaml) を追加する
最後にビルド構成ファイルを作成します。 今回のやりたい手順は次の２つです。

- 前項の Dockerfile を元にカスタムイメージを作成
- カスタムイメージを使って build と deploy を行う

構成ファイルのオプションについては [公式のここ](https://cloud.google.com/cloud-build/docs/build-config?hl=ja) に記載されています。
作成したものは次の通り。

```yaml:cloudbuild.yaml

steps:
#--------------------------------------------------------------------------------
# (1/2) build と deploy に使うカスタムイメージを作成 (Including gcloud, jdk, maven)
#--------------------------------------------------------------------------------
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '--tag=gcr.io/$PROJECT_ID/gcloud-maven', '-f', 'Dockerfile.gcloud-maven', '.']

#--------------------------------------------------------------------------------
# (2/2) カスタムイメージで build と deploy を行う
#--------------------------------------------------------------------------------
- name: 'gcr.io/$PROJECT_ID/gcloud-maven'
  args: ['mvn', 'clean', 'package', 'appengine:deploy']

images: ['gcr.io/$PROJECT_ID/gcloud-maven']
timeout: 1200s
```

※ 各ビルドステップとビルド全体はデフォルトだと
　[１０分でタイムアウト](https://cloud.google.com/cloud-build/docs/build-config?hl=ja#timeout_2) するので必要なら調整します。

以上でデプロイ出来るようになりました。

# Cloud Build でデプロイする
[公式を参考](https://cloud.google.com/cloud-build/docs/running-builds/start-build-manually?hl=ja) にローカルで [`gcloud builds submit`](https://cloud.google.com/sdk/gcloud/reference/builds/submit) コマンドを叩いて Cloud Build を起動します。
ローカルのソースは Cloud Storage 経由でコンテナに渡されます。

デプロイに成功すると次のような感じ。

```
> gcloud builds submit
Creating temporary tarball archive of 9 file(s) totalling 3.9 KiB before compression.
Some files were not included in the source upload.
(中略)
Step #1: [INFO] GCLOUD: To view your application in the web browser run:
Step #1: [INFO] GCLOUD:   $ gcloud app browse --project=springboot-webapp-project
Step #1: [INFO] ------------------------------------------------------------------------
Step #1: [INFO] BUILD SUCCESS
Step #1: [INFO] ------------------------------------------------------------------------
Step #1: [INFO] Total time: 10:04 min
Step #1: [INFO] Finished at: 2019-08-13T07:25:39+00:00
Step #1: [INFO] Final Memory: 32M/99M
Step #1: [INFO] ------------------------------------------------------------------------
Finished Step #1
(後略)
```

上記をWEBコンソールで確認すると次のような感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/41cc6d8d-234a-76b1-4614-82140513b1dd.png)

以上で完了です。

### Cloud Build がコケる場合

もしエラーでコケるようであれば次の画面で手がかりが得られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26808/76dd3d55-a023-be03-9f24-c6e82ec3069f.png)

# デプロイしたアプリを停止する
アプリの停止については [前回の記事](https://qiita.com/items/36b63fd053e383807056) を参考にしてください。

以上です。