雑なメモ: Rails with MySQL on GAE

# 雑なメモ: Rails with MySQL on GAE

とある案件のstaging環境構築模索の一環で探ったことを雑にメモしておく。
いくらか抜けや書き漏れはあるかもしれない。気づいたら治す。

**（なお、他人が見て読みやすいかどうかはほとんど考慮していない）**

## 任意のRailsアプリを GAE へデプロイする

### 1. Cloud SQL for MySQL インスタンスを準備する

まずはチュートリアル文書 [Rails 5 で Cloud SQL for MySQL を使用する ](https://cloud.google.com/ruby/rails/using-cloudsql-mysql?hl=ja) に記載の
> Cloud SQL for MySQL インスタンスを準備する

までを実施しておくべし。

なお、以下は 2019-06-10 時点で上記ページに記載されていた内容の引用。めっちゃ親切。

```
## 始める前に

各ステップを完了したら、そのステップのチェックボックスをオンにしてください。
    
□ Google Cloud Platform Console でプロジェクトを作成します。
    まだプロジェクトを作成していない場合は、このステップで作成します。プロジェクトにより、deployment、アクセス制御、課金、サービスなど、アプリに関するすべての Google Cloud Platform リソースを管理できます。
        1. GCP Console を開きます。
        2. 上部のプルダウン メニューで、[プロジェクトを作成] を選択します。
        3. [詳細設定を表示] をクリックします。[App Engine の場所] で、日本のロケーションを選択します。
        4. プロジェクトの名前を指定します。
        5. プロジェクト ID をメモしておきます。この ID はプロジェクト名とは異なる場合があります。プロジェクト ID はコマンドや構成で使用します。

□ プロジェクトの課金を有効にして、無料トライアルに登録します。
    プロジェクトの課金をまだ有効にしていない場合は、課金を有効化して、無料トライアルに登録します。課金を有効にすると、インスタンスの実行やデータの保存など、課金対象のリソースをアプリで使えるようになります。 無料トライアル期間中は、どのサービスも課金されることはありません。

□ Cloud SDK をインストールします。
    Cloud SDK をまだインストールしていない場合は、今すぐ Cloud SDK をインストールして初期化してください。Cloud SDK には、GCP 上のリソースの作成と管理に使用できるツールとライブラリが含まれています。

□ プロジェクトで API を有効にします。
    GCP Console が開き、このチュートリアルで使用する API が自動的に有効になります。使用される API は Cloud SQL Administration です。

## Cloud SQL for MySQL インスタンスを準備する

このチュートリアルで使用する Cloud SQL for MySQL インスタンスをセットアップします。

    1. 第 2 世代のインスタンスを作成します。このチュートリアルでは、インスタンスの名前は rails-cloudsql-instance です。

    2. インスタンス内にデータベースを作成します。このチュートリアルでは、本番環境のデータベースの名前は cat_list_production です。

    3. インスタンスの root ユーザー パスワードを設定します。
```

### 2. 任意のRailsアプリをローカル開発環境へ用意する

#### Ruby 用のローカル環境のセットアップ （[参照元ページ](https://cloud.google.com/ruby/rails/appengine?hl=ja#ruby-)）

* サンプルアプリ
    * [このへん](https://cloud.google.com/ruby/getting-started/tutorial-app?hl=ja) で提供してくれてる Bookshelf アプリとか。
* SQLプロキシ
    * [このへん](https://cloud.google.com/ruby/getting-started/using-cloud-sql?hl=ja) を参考に。
    * アプリからCloud SQL(MySQL)へ接続する時に必要となる準備のことが詳しく書いてある。
    * 本番環境が使う Cloud SQL のインスタンスへローカル開発環境からもアクセスできるようにするプロキシの実行バイナリが提供されているので、それの使い方を把握すべし。
        * GAE上で稼働するRailsも、結局このプロキシを使う形で動作するので。
* サンプルアプリの起動確認
    1. Cloud SQLへ接続するプロキシを起動する
        * `$ ./cloud_sql_proxy -instances="{{project-id}}:{{region}}:{{SQL-instance-id}}" -dir=/cloudsql`
    2. サンプルアプリのDB（development環境用）を作成する
        * `$ mysql -u hoge -p --socket=/cloudsql/{{project-id}}\:{{region}}\:{{SQL-instance-id}} -e 'create database `dev_bookshelf` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci'`
    3. development環境のRailsアプリを起動し、ブラウザで動作確認する
        * `$ bundle exec rails s`

### 3. アプリを App Engine フレキシブル環境にデプロイする（[参照元ページ](https://cloud.google.com/ruby/rails/appengine?hl=ja#deploy-to-app-engine)）

1. app.yaml を用意する
2. Rails 秘密鍵を構成する
    * 新しい秘密鍵を生成
        * `$ bundle exec rails secret`
    * Googleのドキュメントより引用: 「Rails アプリを本番環境にデプロイする場合、環境変数 SECRET_KEY_BASE に、ユーザー セッション データの保護に使用される秘密鍵を設定します。この環境変数は config/secrets.yml ファイルで読み取られます。」
3. App Engine フレキシブル環境アプリのセットアップ
    * App Engine アプリを作成
        * `$ gcloud app create`
        * Ruby アプリの App Engine フレキシブル環境をサポートするリージョンを選択すること。
    * 本番環境用DBを作成
        1. `$ ./cloud_sql_proxy -instances="{{project-id}}:{{region}}:{{SQL-instance-id}}" -dir=/cloudsql`
        2. `$ mysql -u hoge -p --socket=/cloudsql/{{project-id}}\:{{region}}\:{{SQL-instance-id}} -e 'create database `bookshelf` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci'`
        3. config/database.yml の production セクションへ、Cloud SQLへアクセスするための情報をセットする
        4. `$ RAILS_ENV=production bundle exec rake db:migrate`
        5. `$ RAILS_ENV=production bundle exec rails db:seed`
4. App Engine フレキシブル環境へのデプロイ
    * Rails アセットをプリコンパイル
        * これは、しなくてもよさそう。
        * `$ RAILS_ENV=production bundle exec rails assets:precompile`
    * アセットのコンパイルが完了したら、アプリをデプロイ
        * `$ gcloud app deploy app.yaml`



## Cloud SQL に作成された Rails によるデータへローカル開発環境から直接アクセスしたい場合

[このへん](https://cloud.google.com/ruby/getting-started/using-cloud-sql?hl=ja) を参考に。

* アプリからCloud SQL(MySQL)へ接続する時に必要となる準備(プロキシ等)のことが詳しく書いてあり、その過程で「ローカル開発環境でプロキシを実行してプロキシ経由で Cloud SQL へ `$ bundle exec rake db:migrate` で Rails用のDBを作成」する手順が書いてある。
* 実行したプロキシの生成する socket を Railsが使用して Cloud SQL へアクセスする、というカラクリになっており、つまりそれは mysqlコマンドの `--socekt` オプションでも使えるということ。
* 以下にかいつまんで書いておく
    * ダウンロードしたプロキシコマンドは次のようにして実行する。
        * `$ ./cloud_sql_proxy -instances="[YOUR_INSTANCE_CONNECTION_NAME]" -dir=/cloudsql`
            * 最後の引数「 -dir=/cloudsql」が、socketファイルの生成先ディレクトリ。
            * socketファイル名は次項で乗せるコマンドの表示結果である
    * 注: Cloud SQL インスタンス接続名を調べるには、次のコマンドを実行します。 
        * `$ gcloud beta sql instances describe [YOUR_INSTANCE_NAME]`
    * とはいえ、シェルからmysqlコマンドを実行する時に[YOUR_INSTANCE_CONNECTION_NAME]内の区切り文字となっている「:」はエスケープしてあげないといけないようなので、mysqlコマンドを --socket 指定して実行する際は次のような書式になる。(下記最後の bookshelf の部分はDB名)
        * `$ mysql -u hoge -p --socket=/cloudsql/test-hoge-xxxxxx\:asia-northeast2\:mysql57-test bookshelf`


## deploy後に起動しているインスタンス上で rails console したい場合

1. App Engine メニューの「インスタンス」を開く
2. 操作したいサービス/バージョンを指定してインスタンスリストを表示
3. 起動中の任意のインスタンスの右端にある「SSH」のセレクトボックスから好みの接続方法を選ぶ
    * 手軽なのは「ブラウザウィンドウで開く」で cloud shell を起動すること。
    * なお、この操作により捜査対象 [インスタンスがデバッグモード](https://cloud.google.com/appengine/docs/flexible/java/debugging-an-instance?hl=ja) になる。用が済んだら必ず戻すこと。
4. 起動したシェル上で `docker exec -it gaeapp /bin/sh` を実行し、コンテナに入る
5. `ls -l bin/` でbin/rails に実行パーミッションが立っていることを確認
    * 実行パーミッションが立ってなければ `chmod +x bin/*` とかで立てる
6. `bin/rals c` して、やりたいことを済ませる
7. やりたいことが済んだら、ローカルの操作端末上で `gcloud app instances disable-debug` して、インスタンスのデバッグモードを無効にする