Cloud RunにPhoenixをデプロイする

# 概要

本記事では**GCP**(Google Cloud Platform)の**Cloud Run**にPhoenixアプリケーションをデプロイする手順を解説します。  

また今回は**Terraform**などの**IaC**ツールは使用せず、`gcloud`コマンドのみでデプロイする手順を紹介します。

# ローカル環境

この記事では、以下の環境で開発を行っています。

PC: MacBook
OS: macOS 15.2
またElixir(Erlang)はasdf上で管理しています。
それぞれのバージョンは以下になります。

```bash
% asdf current
Name            Version         Source                                    Installed
elixir          1.18.2-otp-27   /Users/linsei/Docker/Qiita/.tool-versions true
erlang          27.2.2          /Users/linsei/Docker/Qiita/.tool-versions true
nodejs          19.3.0          /Users/linsei/.tool-versions              true

```

# 手順

Cloud Run へ Phoenix アプリケーションをデプロイするには、以下の手順を実行します。  

1. [gcloudコマンドをインストールする](#gcloudコマンドをインストールする)
2. [Google Cloudのプロジェクトを作成する](#google-cloudのプロジェクトを作成する)
3. [Phoenixプロジェクトを作成する](#phoenixプロジェクトを作成する)
4. [GCPのセットアップ](#gcpのセットアップ)
5. [Dockerfileを生成する](#dockerfileを生成する)
6. [Artifact Registryのリポジトリを作成する](#artifact-registryのリポジトリを作成する)
7. [Dockerイメージをリポジトリにpushする](#dockerイメージをリポジトリにpushする)
8. [Cloud Runへデプロイする](#cloud-runへデプロイする)

## gcloudコマンドをインストールする

gcloud コマンドのインストール方法については、以下の公式ドキュメントを参照してください。

https://cloud.google.com/sdk/docs/install?hl=ja

## Google Cloudのプロジェクトを作成する

Cloud Run を利用するために、最初に GCP のプロジェクトを作成します。  
以下のリンクからプロジェクト作成ページを開き、プロジェクト名を入力してください。

https://console.cloud.google.com/projectcreate

以下の画像のように、プロジェクト名を入力して作成しましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455723/32566a94-e83a-4e06-81a0-375e9bc192ee.png" width="50%" />


## Phoenixプロジェクトを作成する

Phoenixプロジェクトを作成しましょう。

今回はデータベースを使用しないため、`--no-ecto` オプションを指定します。（Cloud SQL には無料枠がないため）

```bash
mix phx.new --no-ecto tutorial_gcp
```

## GCPのセットアップ

Phoenixプロジェクトを作成したらCloud Runへのデプロイに必要なGCPの設定を行います。  
以下のコマンドを順番に実行してください。

```bash
# GCPにログインします(別ウィンドウが開くので、ブラウザで認証してください)
gcloud auth login

# 作成したGCPプロジェクトを選択します
gcloud config set project <作成したGCPのプロジェクトID>

# Dockerを使用してイメージを管理するために使用するサービス（Artifact Registry）を有効化
gcloud services enable artifactregistry.googleapis.com 

# DockerイメージをビルドしてCloudRunにデプロイするためのサービス（Cloud Build）を有効化
gcloud services enable cloudbuild.googleapis.com
```

## Dockerfileを生成する

Cloud Run にデプロイするためには、まずPhoenixアプリケーションのDockerイメージを作成する必要があります。  

そのために、以下のコマンドを実行して Dockerfile を生成しましょう。

```bash
mix phx.gen.release --docker
```

## Artifact Registryのリポジトリを作成する

**Artifact Registry**は、Dockerイメージを保存・管理するためのGCPのサービスです。 

Cloud Runにデプロイするため、作成したDockerイメージを保存するリポジトリを作成します。

以下のコマンドを実行して、`repo1` というリポジトリを作成しましょう。

```bash
gcloud artifacts repositories create repo1 \
  --repository-format=docker \
  --location=asia-northeast1 \
  --immutable-tags
```

各オプションの説明

* `repo1` 
    * リポジトリ名
    * :warning: これは Docker イメージを保存するための Artifact Registry のリポジトリ名であり、GitHub とは関係ありません
* `--repository-format=docker`
    * dockerイメージからデプロイするので必須です
* `--location=asia-northeast1`
    * 東京リージョン
* `--immutable-tags`
    * 一度pushしたイメージのタグを編集できないようにする

### 作成したリポジトリの確認

以下のコマンドを実行すると、作成したArtifact Registryのリポジトリ情報を確認できます。

```bash
% gcloud artifacts repositories describe repo1 --location asia-northeast1
```

コマンドを実行すると、リポジトリの詳細情報が表示されます。
この中にある **registryUri**は、次の手順で Dockerイメージをpushする際に必要となるため、コピーしておきましょう。

`registryUri`は、以下のような形式になっています。

```
# registryUri: <リポジトリのドメイン名>/<プロジェクトID>/リポジトリ名
registryUri: asia-northeast1-docker.pkg.dev/tutorial-gcp-451006/repo1
```

## Dockerイメージをリポジトリにpushする

次に、Dockerイメージをビルドし、Artifact Registryにpushします。  
以下の手順で進めましょう。

1. [Artifact Registryへの認証を行う](#artifact-registryへの認証を行う)
2. [Dockerイメージをビルドし、リポジトリにpushする](#dockerイメージをビルドしリポジトリにpushする)

### Artifact Registryへの認証を行う

まず、Artifact Registry への push を許可するために、以下のコマンドを実行します。

```bash
# gcloud auth configure-docker <ドメイン名>
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
```

### Dockerイメージをビルドし、リポジトリにpushする

次に、Dockerイメージをビルドし、Artifact Registryにpushします。
以下のコマンドを実行してください。

```bash
gcloud builds submit --tag asia-northeast1-docker.pkg.dev/tutorial-gcp-451006/repo1/my-app:v1.0
```

**コマンドの説明**

* `gcloud builds submit`
    * 現在のディレクトリにあるDockerfileを探し、Dockerイメージを作成してCloud Buildを使用してpushする
* `--tag (略)/repo1/my-app:v1.0`
    * repo1にイメージ名を`my-app`、タグを`v1.0`で作成しpushする

実行後、しばらく待つと以下のようなメッセージが表示され、push が完了します。

```bash
DONE
--------------------------------------------------------------------------------------------------------------------------------------------------
ID                                    CREATE_TIME                DURATION  SOURCE                                                                                           IMAGES                                                                STATUS
73b915a5-ebab-40da-ad5b-ae2b174736fb  2025-02-15T08:42:54+00:00  2M42S     gs://tutorial-gcp-451006_cloudbuild/source/1739608972.4675-980c49ca33a24b7da7c7438bd924e338.tgz  asia-northeast1-docker.pkg.dev/tutorial-gcp-451006/repo1/my-app:v1.0  SUCCESS
```

## Cloud Runへデプロイする

Docker イメージを Artifact Registryのリポジトリにpushできたら、Cloud Runにデプロイする準備が整いました。  

以下のコマンドを実行して、Cloud Run にデプロイしましょう。

```bash
gcloud run deploy my-service \
  --image asia-northeast1-docker.pkg.dev/tutorial-gcp-451006/repo1/my-app:v1.0 \
  --region asia-northeast1 \
  --allow-unauthenticated \
  --set-env-vars "SECRET_KEY_BASE=$(mix phx.gen.secret)"
```

**コマンドの説明**

* `gcloud run deploy my-service`
    * Cloud Runに`my-service`という名前のサービスでデプロイする
* `--image`
    * デプロイするイメージを指定する
* `--region asia-northeast1`
    * 東京リージョンにデプロイする
* `  --allow-unauthenticated`
    * 認証なしでアクセスできるようにする
* `--set-env-vars "SECRET_KEY_BASE=$(mix phx.gen.secret)`
    * Phoenix の起動に必要な環境変数`SECRET_KEY_BASE`を設定する

# まとめ・感想

今回、初めてCloud RunにPhoenixをデプロイしました。  

`gcloud`コマンドを使うことで、シンプルにデプロイできることを学びました。

また、GCPにもDockerイメージを管理するリポジトリの概念があるという点が非常に面白かったです。

まだ学習していませんが、Terraformを使うと各手順をコード化できるそうなので、  
将来的には同じGCPの環境を再利用しやすくなるのではないかと思いました。

# おまけ

サービスを一時停止したい場合は、以下の操作を行ってください。  

1. Cloud コンソールで `Cloud Run` を検索し、対象のサービスを選択して詳細画面を開く。  
2. スケーリング設定を「自動」から「手動」に変更し、インスタンス数を `0` に設定する。  

これにより、サービスが停止し、課金が発生しなくなります。 

また、Cloud Runの「カスタムドメインを管理」から、デフォルトのドメイン名を変更することも可能です。