GAE(+CloudSQL)環境にElixir+Phoenixをデプロイして動かしてみるまで｡

# はじめに
Qiitaは読む専門でしたが､投稿してみることにしました｡よろしくお願い致します｡

会社で開発合宿があり､GCPについて初めて触れる機会がありました｡
折角なので､GoogleAppEngine+CloudSQL環境にElixir+Phoenixをデプロイしてみようと思います｡

私と同様に､以下のような方を対象としています｡
　・Elixir+Phoenixを使い始めた!
　・GCPという響きにあこがれている!!
　・とりあえず､GCPのアカウントは作成している!!!

# では､やっていきましょう!!!
## GCPの新規プロジェクトを作成
・GCPのダッシュボードから「新しいプロジェクト」を押します｡
<img width="443" src="https://qiita-image-store.s3.amazonaws.com/0/117014/9accfcf6-9b98-78b4-491c-68c6c434a355.png">
<img width="679" src="https://qiita-image-store.s3.amazonaws.com/0/117014/57489c2f-be2f-fd2a-8b77-eb4202d09ec1.png">

・プロジェクト名を決めて､作成ボタンを押します｡
<img width="1085" src="https://qiita-image-store.s3.amazonaws.com/0/117014/73f44504-ae10-726e-149f-d22d2a1c67ba.png">

これだけでプロジェクトは作成出来ます!簡単ですね!!

## GoogleCloudSDKのインストール・初期化
　デプロイ等に利用します!!
　https://cloud.google.com/sdk/docs/?hl=ja
　公式サイトをみてインストールします｡

## CloudSQLのインスタンス作成
・ダッシュボードのハンバーガメニューからSQLを選びます｡
<img width="259" src="https://qiita-image-store.s3.amazonaws.com/0/117014/9f256acf-59ff-36b8-9b31-7e032778b2d9.png">

・インスタンス作成を押して､データベースを選びます｡
<img width="372" src="https://qiita-image-store.s3.amazonaws.com/0/117014/044adb65-b7e9-a912-302d-6867236f059f.png">
<img width="491" src="https://qiita-image-store.s3.amazonaws.com/0/117014/b1f7af4d-9f4c-4538-5eb8-c019778ca0a6.png">

・インスタンスIDを決めて､作成ボタンを押します｡
・<img width="467" src="https://qiita-image-store.s3.amazonaws.com/0/117014/b89087a3-ec07-9354-2c6b-71848a90ccac.png">

これだけでインスタンスは作成出来ます!超簡単ですね!!

## ローカルからCloudSQLProxyを利用してCloudSQLに接続
ローカルから接続出来るって夢ですよね!

https://cloud.google.com/sql/docs/postgres/connect-admin-proxy?hl=ja
公式サイトをみてプロキシをインストールと設定を行います
※プロキシ開始は､TCPかUNIXソケットとありますが､今回はUNIXを利用します｡

・プロキシ開始

```
sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
./cloud_sql_proxy -dir=/cloudsql -instances=<INSTANCE_CONNECTION_NAME> -credential_file=<PATH_TO_KEY_FILE> &
```

・プロキシ接続

```
psql "sslmode=disable host=/cloudsql/<INSTANCE_CONNECTION_NAME> user=<USERNAME>"
```

・接続出来ることを確認します｡

```
Password for user postgres:
psql (11.1, server 9.6.6)
Type "help" for help.

postgres=>
```
おお・・・ローカルからも接続出来ることが確認できました｡

## Elixirプロジェクト作成

・Elixirプロジェクトを作成していきます｡

```
mix phx.new gae_cloudsql_ex_phx --no-brunch
```

・`config/dev.exs` `config/prod.secret.exs`を修正します｡※passwordとsocket_dir

```
config :gae_cloudsql_ex_phx, GaeCloudsqlExPhx.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: ※CloudSQLのユーザパスワード, 
  database: "gae_cloudsql_ex_phx_dev",
  socket_dir: "/cloudsql/<INSTANCE_CONNECTION_NAME>",
  pool_size: 10
```
・CloudSQLとの接続が確認できれば良いので､簡単にAPI作成します｡

```
mix phx.gen.json Api Test tests subject:text
```
・実行後のメッセージに従って､ `lib/gae_cloudsql_ex_phx_web/router.ex`　を編集します｡

```
<略>
  scope "/", GaeCloudsqlExPhxWeb do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
    resources "/tests", TestController, except: [:new, :edit] # <- 追加
  end
<略>
```

・Migrateを実行し､CloudSQL上にDatabaseが作成されているか確認します｡

```
mix ecto.migrate
```

```
Compiling 12 files (.ex)
Generated gae_cloudsql_ex_phx app
[info] == Running GaeCloudsqlExPhx.Repo.Migrations.CreateTests.change/0 forward
[info] create table tests
[info] == Migrated in 0.3s
```

・GCPの画面を確認
<img width="406" src="https://qiita-image-store.s3.amazonaws.com/0/117014/6474ce25-f060-9abb-dc00-159a827441e2.png">
DataBaseが作成されていますね!

・`/templates/page/index.html.eex`を修正し､DB登録・参照だけ実装します｡
※DB接続が確認できればよいので､実装内容は自由です｡

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<div id="app">
  <h1>GetData</h1>
  <div v-for="result in results">
    <div>subject: {{ result.subject }}</div>
  </div>
  <h1>PostData</h1>
  <div>
    <input type="text" v-model="subject">
    <button v-on:click="onCreate">追加</button>
  </div>
</div>
<script>
  new Vue({
    el:'#app',
    data: {results: [], subject: ''},
    mounted() {
      this.getData()
    },
    methods: {
      getData: function() {axios.get('/tests').then( res => {this.results = res.data.data})},
      onCreate: async function() {await axios.post('/tests', {'test': {"subject": this.subject}})}
    }
  })
</script>
```

さぁ､次はデプロイしましょう!!
## デプロイ準備
コミュニティチュートリアルを参考にしながら進めて行きます｡
https://cloud.google.com/community/tutorials/elixir-phoenix-on-google-app-engine?hl=ja

・Distilleryを追加し､コマンド実行
`mix.exs`

```
<略>
  defp deps do
    [
      {:phoenix, "~> 1.3.4"},
      {:phoenix_pubsub, "~> 1.0"},
      {:phoenix_ecto, "~> 3.2"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.10"},
      {:phoenix_live_reload, "~> 1.0", only: :dev},
      {:gettext, "~> 0.11"},
      {:cowboy, "~> 1.0"},
      {:plug_cowboy, "~> 1.0"},
      {:distillery, "~> 1.5"} #<- 追加
    ]
  end
<略>
```
```
mix do deps.get, deps.compile
```
```
mix release.init
```

・構成ファイルも合わせて修正｡
`config/prod.exs`

```
config :gae_cloudsql_ex_phx, GaeCloudsqlExPhxWeb.Endpoint,
  load_from_system_env: true,
  http: [port: System.get_env("PORT")],
  check_origin: false,
  server: true,
  root: ".",
  cache_static_manifest: "priv/static/cache_manifest.json"
```

・以下コマンドを入力しリリース準備します　(一気にできる方法が知りたい)

```
MIX_ENV=prod mix ecto.create
MIX_ENV=prod mix ecto.migrate
MIX_ENV=prod mix release --env=prod
```
## デプロイ
・`app.yaml` を作成

```
env: flex
runtime: gs://elixir-runtime/elixir.yaml
runtime_config:
  release_app: <YOUR_APP_NAME>

beta_settings:
  cloud_sql_instances: <INSTANCE_CONNECTION_NAME>
```

・デプロイコマンド実行

```
gcloud app deploy
※ デプロイ対象プロジェクトを選ぶ場合は以下｡
gcloud app deploy --project=<PROJECT>
```

・しばらく時間がかかるので､コーヒーでも飲みつつ､以下がでるまでまったりします｡

```
Updating service [default] (this may take several minutes)...done.                                                                                                                                                          
Setting traffic split for service [default]...done.                                                                                                                                                                         
Deployed service [default] to [https://<YOUR_APP_NAME>.appspot.com]

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 --project=<YOUR_APP_NAME>
```

## 確認
・URLに接続します｡
<img width="712" src="https://qiita-image-store.s3.amazonaws.com/0/117014/8b5ac04f-bdb0-b68c-6253-0545517e8e0d.png">
・適当にポストしてみます｡
<img width="712" src="https://qiita-image-store.s3.amazonaws.com/0/117014/73a8312f-d83a-cd06-28fa-a08944a4e3b9.png">

無事､登録出来ることが確認できました!!!

## まとめ
今まで環境周りのことって難しい印象でいたんですが､
・GAE+CloudSQLの環境構築が簡単
・CloudSQLProxyでの接続が簡単
・デプロイもコマンド実行で簡単　※時間かかるけど

GCPの場合だと､結構簡単に作れてしまうので､とても身近になった気がしました｡