Cloud Runを使うならこれだけ知ってると得した気分になる

# 結論

- Quick Startに出てくるCloud Buildも少し知ってた方がいい
- Cloud SQL使うならCloud SQL Proxy対応してるので、そのオプションを使う
- インフラにコスト払いたくない、手抜きしたい人には**最高のサービス**

# 実際のアプリケーションを使う場合を想定して使う

Cloud Runの[QuickStart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy)的な記事や内容をよく見ますが、バックエンドで使うならCloud SQLは当たり前に出てくると思う。
なんでCloud SQL（Proxy）と繋ぐ方法は知ってると吉なので書いておきます。

## アプリケーションの作成

今回はRailsでサクッと作ってみるということで

```bash
$ rails new rails_on_cloud_run -T -d postgresql
```

でまずはサクッとRailsプロジェクトを作ります。

## Dockerfileおよびstartファイル作成

Cloud RunはDockerコンテナで動くので、`Dockerfile`が必須です。そのDockerコンテナの起動に使う`start`ファイルを一緒に作ります。

```docker
FROM ruby:2.6.3-alpine

RUN apk add --no-cache tzdata postgresql-dev && \
  cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN mkdir /app
WORKDIR /app

ARG BUNDLE_OPTIONS

COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN apk add --no-cache --virtual .rails-builddeps alpine-sdk && \
  bundle install -j4 ${BUNDLE_OPTIONS} && \
  apk del .rails-builddeps

COPY . /app

CMD ["bin/start"]
```

手抜きのようで必要最低限の`Dockerfile`。かくゆう私は基本この`Dockerfile`から始めます。
で最後の`CMD`に書いてる`start`ファイルを作ります。

```bash
#!/bin/sh

RAILS_PORT=3000
if [ -n "$PORT" ]; then
  RAILS_PORT=$PORT
fi

# db migrate
# TODO 後でJobに切り出したい
bin/rails db:create
bin/rails db:migrate

bin/rails s -p $RAILS_PORT -b 0.0.0.0
```

ここで大事なのは`PORT`という環境変数があったら、そのポートでRailsを起動していること。
Cloud Runでは`PORT`という環境変数が渡ってきて、そのポートで起動してるかのチェックが行われます。なので指定されたポートで起動する必要があるため、このような記載になっています。

## Cloud SQLへの接続設定

ここまでで確かにビルドはできるのですが、もう1つ大切なことがあります。
それはCloud SQLへ繋ぐための設定です。Cloud SQLへの接続はCloud SQL Proxyを介して接続することが推奨されています。（もちろんなくてもできますが）
そこでそのCloud SQL Proxyを使うためにDatabase接続の定義を修正します。Railsの場合はdatabase.ymlなので例として

```yaml
default: &default
  adapter: postgresql
  encoding: utf-8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV['DB_HOST'] || 'localhost' %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  port: <%= ENV['DB_PORT'] %>
#  socket: <socket path> # for MySQL

production:
  <<: *default
  database: <your database name>
```

単に環境変数から取得しているのですが、大事なのは接続先です。Cloud SQL Proxy対応のCloud Runコンテナはコンテナ内の`/cloudsql/<Cloud SQL instance>` にsocketがあるのでそこに向けて接続する必要があります。PostgreSQLの場合は上記のyamlファイルのhost部分をそれに指定し、MySQLの場合はsocket部分を指定できるようになればいいです。

ちなみにその`DB_HOST`の指定は`/cloudsql/<Project ID>:<region>:<Cloud SQL Instance name>`になると思います。
もしCloud SQLへの接続名がわからないならConsoleからはこんな感じで見えるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70363/6e5637af-83cb-3853-7e27-8556bca9d4c9.png)

## Cloud Build（Docker build）の設定

上記に記載したリンクのQuick Startに`gcloud builds submit`というコマンドが出てくるが、これがDockerイメージをビルドするためのサービスを起動するコマンドです。
そのコマンドを使うと確かにビルドできるのですが、Production等で使用する場合にビルド時間の短縮とかを考える必要あります。そこでCloud Buildでは[kaniko](https://github.com/GoogleContainerTools/kaniko)が使えます。kanikoはビルドする時に前回のビルド時キャッシュを使用してビルドすることでビルド時間を短縮します。（詳しくは説明しませんので、ググって下さい）

kanikoを使うで最低限必要なyamlファイル

```yaml
steps:
- name: 'gcr.io/kaniko-project/executor:latest'
  args:
    - --build-arg=BUNDLE_OPTIONS=--without development test
    - --destination=gcr.io/<Project ID>/<image name>:latest
    - --cache=true
```

`name`にkanikoを使うイメージ名を指定することで使用することが可能です。使える引数とかはkanikoのドキュメントを見れば大体わかると思います。必要なのは`cache`と`destination`。`cache`は前回ビルドのキャッシュを使うかどうか、`destination`はビルドしたイメージをどのリポジトリに登録するかの指定です。
`build-arg`については上記の`Dockerfile`でARGを指定していた部分があります。Railsの場合はProductionでは不要なgemのインストールを避けるためにこんな感じで逃げることができます。

このyamlファイルを指定して実行するには

```bash
$ gcloud builds submit --project <Project ID> --config ./cloudbuild.yml
```
で実行すればOKです。`project`を付けてるのは自分の場合は複数プロジェクトを使用する場合があるので、ほぼほぼ必死なので付けてるだけです。

ちなみにこのkanikoを使うなら以下のコマンドを叩いてkanikoの使用を有効化する必要があります。

```bash
$ gcloud config set builds/use_kaniko True
```

## Cloud Runのデプロイ

ここまで来たら最後はデプロイです。
デプロイの時に大切なのは、Cloud SQL Proxyを使用するオプションを付けることが大事です。
サクッとデプロイコマンドを貼ると

```bash
$ gcloud beta run deploy <Cloud run service name> \
  --project <Project ID> \
  --image gcr.io/<Project ID>/<image name> \
  --region us-central1 \
  --add-cloudsql-instances <Project ID>:<region>:<Cloud SQL Instance name> \
  --set-env-vars RAILS_ENV=production \
  --set-env-vars RAILS_MASTER_KEY=<Rails master key> \
  --set-env-vars DB_USERNAME=<database user name> \
  --set-env-vars DB_PASSWORD=<database password> \
  --set-env-vars DB_HOST=/cloudsql/<Project ID>:<region>:<Cloud SQL Instance name>
```

`add-cloudsql-instances`というオプションがCloud Runで実行するコンテナにCloud SQL Proxyを使用するようにしています。これで先程指定したunix socketのファイルが生成されるので、Cloud SQLへ接続できるようになるはずです。

# 最後に

アプリケーションを使用する上で最低限必要なものを想定して使用すると課題も出てきます。
Cloud Runのbetaリリース当初はCloud SQL Proxyの設定はなく、泣く泣くDockerイメージの中にCloud SQL Proxyをインストールして使っていたのですが、対応されたことにより上記のよう設定だけで完了できるようになりました。
AWSも素晴らしいですが、GCPもこういった素晴らしいサービスが多々あるので、必要なものを取捨選択できるような状態になるのが好ましいですね。

# 参考URL

https://cloud.google.com/run/docs/quickstarts/build-and-deploy
https://cloud.google.com/run/docs/configuring/connect-cloudsql
https://cloud.google.com/cloud-build/docs/kaniko-cache