GCPのAppEngineでRedmineを起動したときのメモ


## はじめに
 職場でRedmine使って色々管理している流れで、ちょっと自宅でお試し環境を作りたくなり、ついでにGCPのAppEngineも試したかったので、AppEngine上でRedmineを実行してみた際の手順をまとめてみました。

## 参考
* [GCPのRailsチュートリアル](https://cloud.google.com/ruby/rails/appengine)
* [GCPのCloud SQLマニュアル(AppEngineからの接続方法について)](https://cloud.google.com/sql/docs/postgres/connect-app-engine)

## 環境
* ローカルにgcloudコマンドラインツールを入れるのが面倒だったので、GCPのコンソールから支えるCloudshellから操作を行いました。
* データベースにはCloud SQLを使って構築したPostgreSQL11を使っています。
* mysqlを使わなかった理由： Cloud Shell環境でgem install mysql2が失敗したから。(mysql-develが必要なのだが、Cloud Shell環境にインストールするのは難しそうだとハナから諦めました。) 
* AppEngineはFlexible環境を使いました。
* 標準環境を使わなかった理由： Ruby2.5の環境がなかったから。

## 手順
### まずは、プロジェクトを作成します。
Cloud Shellなら、gcloudコマンドがすぐに使えて楽。

```shell:shell
# ここでは"testtest-001"という名前のプロジェクトを作っています。
gcloud projects create testtest-001 --name testtest-001

# 作ったら、カレントプロジェクトに設定してあげます。
gcloud config set project testtest-001
```

### 次に、データベースのインスタンスを作成
PostgreSQL 11のインスタンスには仮想サーバのサイズ指定が必要とのことで、cpuとmemoryサイズを指定しています。(1cpu, 4GB memoryにしておきました。)

```shell:shell
gcloud sql instances create test-redmine-001 --no-backup --database-version=POSTGRES_11 --root-password=PASSWORDYYYYMMDD --region=asia-northeast1 --cpu=1 --memory=4G
```

できたか確認します。

```shell:shell
gcloud sql instances describe test-redmine-001
```

一応、コンソールからも確認してみたところ、
「課金を有効にしますか？」
的な事を聞かれます。
躊躇したくなりますが、無料トライアル期間中なので、OKしてしまった。
（無課金では試せません。あしからず。。）

### Cloud SQL APIを有効にします。
全てコマンドでできました。

```shell:shell
# まず、Cloud SQL Admin APIのサービス名を確認
gcloud services list --available | egrep "SQL"

# => 結果から、sqladmin.googleapis.comをコピーしまして。

# まず、Cloud SQL Admin APIを有効化
gcloud services enable sqladmin.googleapis.com

# => 以下のような結果になればOK
# Operation "operations/[なんかのID]" finished successfully.
```

### 続いてCloud Build APIも有効化します。
SQL Admin APIの際とほとんど似たような手順(名前を確認して有効化)ですね。

```shell:shell
gcloud services list --available | egrep "build"
=> cloudbuild.googleapis.com
gcloud services enable cloudbuild.googleapis.com
```

### そしたら、CloudBuildのサービスアカウントに編集者権限を付与
ここ、Cloud Build APIを有効化しておかないと、「そんなアカウントはありません」エラーとなりますのでご注意を。

```shell:shell
gcloud projects add-iam-policy-binding [プロジェクトID] --member=serviceAccount:[プロジェクト番号(※)]@cloudbuild.gserviceaccount.com --role=roles/editor

# 例
# gcloud projects add-iam-policy-binding testtest-001 --member=serviceAccount:123456789012@cloudbuild.gserviceaccount.com --role=roles/editor

# ※プロジェクト番号は以下のコマンドの結果で調べられます。（一番右の数字。。PROJECT_IDじゃないので気をつけましょう。）
gcloud projects list
# 出力例>
# PROJECT_ID    NAME          PROJECT_NUMBER
# testtest-001  testtest-001  123456789012
# testtest-003  testtest-003  345678901234
```

### いよいよ、redmineの本体を準備。
#### まずはgithubからredmine本体を取得。

```shell:shell
# githubからcloneします。
git clone https://github.com/redmine/redmine.git
```

#### そしてdatabase.ymlの設定

```shell:shell
# redmineのディレクトリに移動
cd redmine
# database.yml.exampleをコピーしてdatabase.ymlを作る(自信ある方はゼロから作っても大丈夫。)
cp config/database.yml.example config/database.yml

# コピーできたら、database.ymlの編集です。
# production環境の接続設定だけいじりました。
vi config/database.yml
# 中身は次のセクションを参照してください。
```
database.ymlの中身はこちら。

```yaml:database.yml
production:
  adapter: postgresql
  database: redmine
  host: '/cloudsql/testtest-001:asia-northeast1:test-redmine-001'
    # <= "/cloudsql/" に
　  # <= "gcloud sql instances describe インスタンス名"で取得したconnectStringの値をつなげるのです。
  username: postgres
  password: "PASSWORDYYYYMMDD" # <= postgresユーザのパスワード
```

#### 次、デプロイに便利なappengineを追加
appengineはGCP環境にrubyアプリをデプロイするための便利Gemです。
bundle addしてから、bundle installします。

```shell:shell
# まずはappengineをGemfileに追加。(直接編集しても良い。)
bundle add appengine

# そして、bundle installといきます。
# (これやらなかったら、あとのデプロイ(gcloud app deploy)で失敗した。。)
bundle install
```

#### そして、appengineにデプロイしてもらうためのapp.yamlを作ります。
チュートリアルには作る場所がはっきり書かれてない気がしますが、アプリケーションのルートディレクトリに作ります。
(githubからクローンした人は、redmineディレクトリ直下です。)

``` yaml:app.yaml
# まずはチュートリアルからもらった内容をそのまま書いてしまいます。
entrypoint: bundle exec rackup --port $PORT
env: flex
runtime: ruby

env_variables:
  SECRET_KEY_BASE: [SECRET_KEY]

beta_settings:
  cloud_sql_instances: [YOUR_INSTANCE_CONNECTION_NAME]
```

そして、上のファイルの[SECRET_KEY]を以下のコマンドの結果で上書きします。

```shell:shell
bundle exec rails secret

# 出力例=>
881cf9bd..... 長いのとセキュリティ上良くないので以後省略。。すみません。
```

さらに、[YOUR_INSTANCE_CONNECTION_NAME]
をインスタンス接続名で上書き。
(/cloudsql/は書きません。)

以下実際に設定してみたサンプルです。

``` yaml:app.yaml
# 実設定入れてみた感じ。
entrypoint: bundle exec rackup --port $PORT
env: flex
runtime: ruby

env_variables:
  SECRET_KEY_BASE: 881cf9bd.....(本当はすげー長い。)

beta_settings:
  cloud_sql_instances: testtest-001:asia-northeast1:test-redmine-001
```

### ようやくAPP Engineを作ってデプロイ！
こちらもコマンドで。
今回の手順、コンソールを使う作業はほとんど行いませんでした。

```shell:shell
gcloud app create --region=リージョン名(ap-northeast-1などなど)
# --regionを指定しない場合は、途中で聞かれます。
# 仕掛けて、トイレ行って戻ったときに終わってなくてがっかりしました。
```

できたかな？
できたら、デプロイ！！(急ぎすぎですが、大丈夫。)

```shell:shell
gcloud app deploy
# 途中で確認画面が出ますので元気に"Y"で答えましょう。
```

### そして一度失敗を経験する。
先ほどのコマンドですが、最後必ず失敗します。

```shell:deploy-error
Updating service [default] (this may take several minutes)...failed.
ERROR: (gcloud.app.deploy) Error Response: [9]
Application startup error! Code: APP_CONTAINER_CRASHED
bundler: failed to load command: rackup (/app/vendor/bundle/ruby/2.6.0/bin/rackup)
ActiveRecord::NoDatabaseError: FATAL:  database "redmine" does not exist

# => そりゃそうだよ、redmineなんていうデータベース作ってないもん。
```

### 気を取り直してDBの準備。
失敗しても落ち込む暇はないのです。
DBを準備しましょう。

```shell:shell
# まずはデータベースを作成
bundle exec rails appengine:exec -- bundle exec rails db:create

# 出力例
# ---------- CONNECT CLOUDSQL ----------
# cloud_sql_proxy is running.
# 
# ---------- EXECUTE COMMAND ----------
# bundle exec rails db:create
# Created database 'redmine'
# 
# ---------- CLEANUP ----------
# PUSH
# DONE
#
# 次にテーブルの作成など。
bundle exec rails appengine:exec -- bundle exec rails db:migrate

# 出力例
# ---------- CONNECT CLOUDSQL ----------
# cloud_sql_proxy is running.
# 
# ---------- EXECUTE COMMAND ----------
# bundle exec rails db:migrate
# 
# ...ここから、create table結果の嵐。
# 
# ---------- CLEANUP ----------
# PUSH
# DONE
#

# んで、デフォルトデータの投入(これやらないと使い物にならんですね。redmine)
bundle exec rails appengine:exec -- bundle exec rails redmine:load_default_data REDMINE_LANG=ja
# <= コマンドの後ろに"REDMINE_LANG=ja"で使用言語を設定しているところがミソ。
# <= 。。。無いとプロンプトが返されるみたいでタスクが失敗します。

# 出力例
# ---------- CONNECT CLOUDSQL ----------
# cloud_sql_proxy is running.
# ---------- EXECUTE COMMAND ----------
# bundle exec rails redmine:load_default_data REDMINE_LANG=ja
# Default configuration data loaded.
# ---------- CLEANUP ----------
# PUSH
# DONE

```

### 隊長！起動準備が整いました。

* アプリケーションはエラーを起こしながらもデプロイはできた。
* データベースインスタンスを起動して、redmine用のデータベースもできた。
* データベースのテーブル作成もできた。
* デフォルトデータも投入した。

ということで、起動準備完了。
先ほどデプロイに失敗したやつを起動して差し上げます。

```shell:shell
# まずはサービスの状態を確認。
> gcloud app versions list
# 出力例(STOPPEDになってますね。)
# SERVICE  VERSION.ID       TRAFFIC_SPLIT  LAST_DEPLOYED              SERVING_STATUS
# default  20200412t165521  1.00           2020-04-12T11:00:15+09:00  STOPPED

# そしたら、起動
> gcloud app versions start 20200412t165521

# 出力例
# Starting the following versions:
#  - testtest-001/default/20200412t165521
Do you want to continue (Y/n)?  Y <= 続けてよいか聞かれるのでYを答える。

# Waiting for operation [apps/testtest-001/operations/349e4332-2923-40de-a840-12f034daa670] to complete...done.
```

### 隊長！お気を確かに！！
!!やった起動成功！！！と誰もが思います。
早速、ページが開けるかみてみましょう。
ページのアドレスは以下のコマンドで確認できます。

```shell:shell
gcloud app services browse default --no-launch-browser

# 出力例
SERVICE  URL
default  https://testtest-001.an.r.appspot.com
```

ブラウザにアドレスをコピペして。。。
表示！！でき。。ない。
・・・Temporary Unavailable的なメッセージが。。
・・・30秒後にもう一回来いとな。

### 任務完了
ということで、念のため１分待ってからもう一回アクセス。
やっと会えた！
<img width="1262" alt="スクリーンショット 2020-04-13 15.27.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244595/b433e172-2cd8-4111-2076-3d99f62c13d1.png">


## ハマったことまとめ。

* サービス起動してからページが開けるようになるまでに、結構時間がかかるのを知らず、最初は非常に焦って、色々調べてしまいましたが、「待てば良い」それだけでした。
* 他にも、API有効化してから使えるようになるまで、タイムラグがある感じがします。ので、「ちょっと待ってみる」気持ちの余裕が必要かと。
* 当初、Cloud ShellはApp Engineの実行環境ではない。というのになかなか気がつかず（お恥ずかしい。。）、プロジェクト移動したのに同じディレクトリが見えるのが「何かの間違い」だと思い込み、無駄な時間を過ごしました。
* ドキュメントページに用意されているチュートリアルを試さずに始めてしまったので、理解に時間がかかりました。やはり、チュートリアル素晴らしい。