Rails・MySQLのアプリをFly.ioでデプロイする

## はじめに
Fly.ioはRailsアプリをデプロイすることも可能なサービスです。

Fly.ioを使ってRailsアプリをデプロイする手順は他の記事にも書いてあるのですが、MySQLを使う場合の手順が見つけられなかったので記載します(PostgresSQLだとターミナルに表示される指示に従えば、自動的に環境作れるのですが、MySQLだとちょっと手順が増えるため、覚え書きとして記載します)。

また、Fly.ioのデプロイは無料という記事が出ていますが、それは少し前までの話で、今は一番安いプランでも月に$5かかりそうです。

> Plan料金: https://fly.io/plans

## 実行環境
実行環境は以下になりますが、別のOSでも若干コマンドが違うだけで大まかな手順は一緒になると思います。
- MacBook Air M3チップ
- lima(ubuntu22.04イメージ,aarch64)
- Docker version 25.0.4

## 手順
### 手順0: Railsアプリを作成する
Fly.ioにデプロイするためには、まずはRailsのアプリを作成している必要があります。
もし、Railsアプリを作成していない場合は、以下の記事の手順などでRailsアプリを作成することができます。
この記事は執筆時点(2024年3月)で「いいね0、ストック0」の状態なので、良かったらいいねボタンかストックボタン押していただけると嬉しいです。

https://qiita.com/yuta-saito-0310/items/c2368227aae21bafcad7

記事読むのも面倒だったら、以下のリポジトリをフォークするなり、ダウンロードするなりして頂いても大丈夫です。

https://github.com/yuta-saito-0310/practice_devcontainer

### 手順1: Fly.ioに登録する
以下のサイトからFly.ioに登録します。

https://fly.io/

登録が終わったら、Dashbord > Billing > Add credit cardからクレジットカードを登録します。最初にも述べましたが、現在は料金体系が変わっていることもあり、無料期間の１ヶ月が終わったら課金されるかもしれません。料金体系については[こちら](https://fly.io/docs/about/pricing/)を確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525646/358ca875-4984-f702-377e-68b6d30d3f4f.png)



### 手順2: flyctlをインストールする
OSに合わせたコマンドを選択して、flyctlをインストールします。
flyctlはコマンドでFly.ioとやり取りをするために必要なツールで、デプロイするときとかに使います。

https://fly.io/docs/hands-on/install-flyctl/

私はLinuxを利用しているため、ターミナルで以下のコマンドを実行します。
```
curl -L https://fly.io/install.sh | sh
```

コマンド実行後、以下のようなメッセージが表示されたので、それに従って環境変数を設定します。(環境によって内容が違うと思うので、メッセージを確認してください)
```
flyctl was installed successfully to /home/yuta-saito.linux/.fly/bin/flyctl
Manually add the directory to your $HOME/.bash_profile (or similar)
  export FLYCTL_INSTALL="/home/yuta-saito.linux/.fly"
  export PATH="$FLYCTL_INSTALL/bin:$PATH"
```

私の環境では上のようなメッセージが出ていたため、指示に従って`vi ~/.bash_profile`などで、以下の内容を記載し、shellの起動時に環境変数が設定されるようにします。

```
export FLYCTL_INSTALL="$HOME/.fly"
export PATH="$FLYCTL_INSTALL/bin:$PATH"
```

環境変数が反映され、flyctlが使えるようになったことを確認するために、一度ターミナルを再起動します。

```
sudo reboot
```

再起動後に以下のようにflyにログインします。

```
flyctl auth login
```

ログインした後に、`flyctl auth whoami`でログインアカウントが表示されればOKです。

### 手順3: MySQLコンテナをデプロイする
Railsアプリをデプロイする前にFly.ioではMySQLのコンテナを先に起動させる必要があります。PostgresSQLだと、Railsアプリのデプロイと同時にDBコンテナを起動させるオプションがあるのですが、MySQLではその手順が無いので、自分でコンテナを立ち上げる必要があります(おそらく)。

そのために、まず以下のようにディレクトリを作成します。
```shell
mkdir mysql-fly-saito
cd mysql-fly-saito
```

その後、次のコマンドを実行してデプロイの準備を始めます。

```
fly launch --no-deploy --image mysql:8
```

この時`Do you want to tweak these settings before proceeding? (設定を微調整しますか？)
`と聞かれるので、yを入力して設定を調整します。

app名は自分の好きなもので、まだ作成されていないものを、regionは自分の近所、portは3306、vmはshared-cpu-1xの1GBを選択します。他はデフォルトの入力で大丈夫です。(vmのメモリを256MBにすると、メモリ不足で立ち上がらない場合があるので、1GBに設定しています)

ブラウザ上で設定をすると、fly.tomlが作成されていると思います。

作成されたtomlファイルを以下のように修正します。

 > 参照: https://fly.io/docs/app-guides/mysql-on-fly/

```toml
# fly.toml app configuration file generated for mysql-fly-saito on 2024-03-27T16:23:03+09:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = 'mysql-fly-saito' # 自動入力されるので編集しない
primary_region = 'nrt'

[build]
  image = 'mysql:8'

[http_service]
  internal_port = 3306
  force_https = true
  auto_stop_machines = true # コンテナをずっと稼働させたい時はここをfalseにする
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[vm]]
  memory = '1gb' # デプロイ時にメモリ不足になる可能性があるため、1GBに設定
  cpu_kind = 'shared'
  cpus = 1

[processes]
  app = """--datadir /data/mysql \
    --default-authentication-plugin mysql_native_password"""

[mounts]
  source = "mysqldata"
  destination = "/data"
```

tomlファイルを作成したら、ボリュームを作成します。ボリュームはデプロイし直した時とかに、DBのデータを保持するためのものです。今回は1GBを指定します。

```
fly volumes create mysqldata --size 1
```

また、MySQLのルートユーザーのパスワードをシークレットで設定します。

```
fly secrets set MYSQL_ROOT_PASSWORD=sample-password
```

上が設定し終わったら、MySQLをデプロイします。

```
fly deploy
```

デプロイが成功していると、ダッシュボードのAppsで緑色のマークが表示されていると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525646/37666b21-3c02-6a90-9b3b-8a8f3a2050ec.png)

もしもデプロイに成功しておらず、Suspendedの状態になっていた場合は、アプリ名をクリック > Live Logsからエラーの原因を探していきます。

### Railsアプリのデプロイ
上でMySQLの準備ができたので、Railsアプリを作成していきます。
ただ、Gitでクローンしたリポジトリなどはマスターキーがないと思うので、マスターキーを用意します。(自分で作ったリポジトリは、rails newをした時に一緒にマスターキーが作成されているのでこの手順は不要です)

以下のコマンドを開発コンテナ内などのRailsが実行できる環境で実行し、master.keyを再生成しておきます。

```
rm config/credentials.yml.enc
rails credentials:edit
```

次に、デプロイの準備をしていきます。
開発コンテナ内で以下のコマンドを実行します。

:::note warn
[手順2-flyctlをインストールする](#手順2-flyctlをインストールする)をコンテナ内で再実行しないとコンテナ内でflyctlを実行できません。
コンテナ内で環境変数を設定するのに、bash_profileを編集するのではなく、exportをターミナル上で実行して環境変数を設定します(他に良い方法あれば教えて頂けると助かります)
:::



```
fly launch --no-deploy 
```

flyctlはプロジェクトのソースコードを読み込んでfly.tomlを作成してくれるので、殆ど作業はいらないのですが、デプロイ前に環境変数などを先に設定しておきます。

:::note warn
`DB_HOST`に指定するホスト名だけ注意が必要です。アプリをlaunchした時に出るホスト名ではなく、`アプリ名.internal`というような名前で指定しないと、DBのセットアップ時に`Connection Error`が発生してしまいます。
:::

```
fly secrets set RAILS_MASTER_KEY=$(cat config/master.key)
fly secrets set MYSQL_ROOT_PASSWORD=sample-password
fly secrets set DB_HOST=mysql-fly-saito.internal # MySQLアプリ名.internalというような名前を載する
fly secrets set PROD_DB_NAME=ProdDB
```

上で環境変数を設定したら以下のコマンドでデプロイを実行します。
割と時間がかかり、自分の場合は20分ほど待ちました。

```
fly deploy
```

デプロイが完了するとダッシュボードのAppsが緑色になっています。
flyのアプリページに、デプロイ先のURLが記載されているのでアクセスしてみましょう。

`fly deploy`した後に、Suspendedの状態になっていると、おそらくデプロイに失敗しているので、Live Logsから原因を調べていきます。

## 終わりに
以上がFly.ioでRailsアプリをデプロイする手順となります。
コマンドとファイルを少しイジるだけでデプロイすることができるので、今までデプロイを経験したことが無かった自分でもデプロイまですることができました。

ただ、MySQLでデプロイするよりも、Postgresでデプロイする方が楽なので、初めからFly.ioでデプロイすると決めているのならPostgresでデプロイする方が良いように思えます。