Fly.ioへSpring Boot（＋Postgres）アプリケーションをデプロイする

fly.ioというサイトにSpring Bootのアプリをデプロイしていきます。
そんな記事です。

## やりたいこと

- できるだけ安くSpring Bootのアプリをデプロイしたい。
- データベース（Postgres）にアクセスするアプリにしたい。

## やること

前掲の目的を色々検討した結果、Fly.ioというプラットフォームを使用することにしました。

[Fly.io公式](https://fly.io/)

無料でポスグレちゃんを使わせてくれるところが他に見当たりませんでした。
NoSQLデータベースの方がタダのところ見つけやすいと思います。
今回は諸事情でRDBを使わざるを得なかったので…。

## 参考資料

この記事を書くにあたっては以下のサイトから情報を得たり参考にしたりパクらせて頂きました。
感謝(@_@)

[Herokuの代替として注目のFly.ioでアプリケーションをデプロイする](https://zenn.dev/hokawa/articles/65ddcd9974448c)
[Fly.ioの無料枠へSpring Bootアプリケーションをデプロイする](https://zenn.dev/backpaper0/articles/3f840d391da4c5) （←このサイトだけ見ればいいじゃんって思うと思うけど、このサイトだけだとわからない人がいると思う。というか分からなかったのでこの記事を書いてる。）

## 前提条件（免責事項）

Fly.ioで検索すると「無料枠で～」という記事が色々ひっかかるのだけど、どうも自分が試した限りにおいてはアプリのデプロイをしようとするとクレジットカードの登録するまで許してくれなかった。んで、クレジットカードを登録するとトライアルモードから自動的にHobbyプランに切り替わり、プランのページには月＄5って書いてあるの（[Plan Pricing](https://fly.io/plans/personal)）。
Fly.ioのページ見る限り「無料のリソース」があるだけであってタダのプランなんてモンはないと書いてあるように見える…。（[Fly.io Resource Pricing](https://fly.io/docs/about/pricing/)）
自分もガチャガチャやってる間に＄0.01課金されてしまったが、退会したら「＄5未満だから請求しないでおいてやんよ」みたいなありがたいメールが届いて支払いを免れたようだ。現時点でリソースを削除してるし、1か月経ってないから実際のところがようわからん。そもそも料金体系はサービス提供側の都合でいくらでも変わりうる。ネットの（特に過去の）情報を鵜呑みにしてはいけない。でもとりあえず少なくとも月＄5は覚悟しておいたほうがいい。
というわけで自己責任でよろしくね。（タイトルからは「無料」の文言は消した）

## 環境

- Win10（Win11買えないから）
- VSCode
- Java 17
- Spring Boot 3.2.1
- Postgres（バージョンよくわかんね） [Fly Postgres](https://fly.io/docs/postgres/)
- MyBatis 3.0.3

## Spring Bootのアプリを用意する。

用意できていなければspring initializrというサイトで適当に作ります。

[spring initializr](https://start.spring.io/)

![Flyioにアプリをデプロイする_2024-01-17-00-12-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/996a6dd0-1946-7138-ed95-9acdfa1907af.png)

細かいバージョンはしょっちゅう変わりますが、あんまり気にしなくて大丈夫だと思います。
今回、Postgresを使ったWebアプリをデプロイするので、以下の依存性（Dependencies）を追加しておきます。

- Spring Web
- MyBatis Framework（これじゃなくてもいいけど）
- PostgreSQL Driver

「GENERATE」ボタンでプロジェクトディレクトリを固めたzipファイルがダウンロードできます。
解凍してできたディレクトリをVSCodeで開いておきましょう。

![Flyioにアプリをデプロイする_2024-01-17-08-08-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/2863e22e-ecd1-2136-b91a-7bae61dd3b3f.png)


適当にDBアクセスするマッピングメソッドを追加しておきます。何でもいいです。

![Flyioにアプリをデプロイする_2024-01-17-08-11-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/d0a62f5a-6f0d-67ff-3a22-d561645b8b4d.png)


適当にSQLも用意しておきます。

![Flyioにアプリをデプロイする_2024-01-17-08-38-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/7a6069d1-be9c-c887-d5bf-0f2c95fe9aee.png)


DB接続情報は環境変数からぶち込む設定としておきます（YAMLなのは趣味）。
ここでは以下の環境変数としました。

- URL：DATABASE_URL
- ユーザ：DATABASE_USER
- パスワード：DATABASE_PASSWORD


## Fly.ioにサインアップする

[Fly.io公式](https://fly.io/)

![Flyioにアプリをデプロイする_2024-01-16-23-34-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/720d9501-7404-243e-5fab-5fa3efda5711.png)


右上の「Sign Up」ボタンからアカウント登録してください。
後述のCLIからもアカウント登録はできるみたいです（やったことないけど）。

![Flyioにアプリをデプロイする_2024-01-16-23-36-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/2264ec14-70ea-20fa-1291-58087f8a354f.png)


GithubアカウントやgmailなどでSSOもできる。自由に選んでください。

### クレジットカードを登録する

ついでに前掲の理由の為、クレジットカードを登録しておいてください。

![Flyioにアプリをデプロイする_2024-01-17-23-26-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/73a07a22-dc41-bcab-be66-df8a44b13869.png)

サインアップ（サインイン）後の画面右上あたりの「Add a payment method」から登録できます。

![Flyioにアプリをデプロイする_2024-01-17-23-28-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/86c40116-0221-b888-cadd-11995a33f46d.png)


チェックボックスはチェックしなくてもよいです。

## CLI（flyctl）をインストールする

CLIはCommand Line Interfaceの略で、要するにコマンドプロンプトから実行できるアプリだと思ってください。

参考
[Install flyctl](https://fly.io/docs/hands-on/install-flyctl/)

flyctlというCLIをインストールします。
PowerShellで以下を実行してください。VSCodeでターミナルを開けばデフォルトがPowerShellになっていると思います。

```
iwr https://fly.io/install.ps1 -useb | iex
```

正常にインストールできれば```fly```または```flyctl```コマンドが使えるようになります。

### flyctlでサインインする

以下のコマンドでサインインしましょう。

```
fly auth login
```

ブラウザにフォーカスが移動してブラウザ上でサインインすることになると思います。
サインイン成功したらブラウザは閉じて大丈夫です。

## DBを作成する

APより先にDBを用意しておきます。

参考
[Create a Fly Postgres Cluster](https://fly.io/docs/postgres/getting-started/create-pg-cluster/)

Postgresのクラスタを作成します。

```
fly postgres create
```

```
? Choose an app name (leave blank to generate one): <Postgresアプリケーション名>
? Select region: <リージョン>
? Select configuration: Development - Single node, 1x shared CPU, 256MB RAM, 1GB disk
? Scale single node pg to zero after one hour? Yes  
```

いくつか質問されるので目的に沿ってカスタマイズしてください。

- Postgresアプリケーション名：これは適当でいいです。
- リージョン：Tokyo, Japan (nrt)を選択してください。
- 構成：Developmentを選択してください。他のを選択すると地獄の課金が始まるかもしれません。
- 接続がない場合は1時間後にインスタンス無にスケールダウンするかどうか。：y

クラスタ作成完了後、接続情報が表示されます。ここでメモっておかないと二度と接続できなくなります。

```
Postgres cluster <Postgresアプリケーション名> created
  Username:    <Postgresユーザ名>
  Password:    <Postgresパスワード>
  Hostname:    <Postgresアプリケーション名>.internal
  Flycast:     <IPv6アドレス>
  Proxy port:  5432
  Postgres port:  5433
  Connection string: postgres://<Postgresユーザ名>:<Postgresパスワード>@<Postgresアプリケーション名>.flycast:5432
```

接続文字列が表示されていますが、この形式はSpring Bootアプリケーションでは使用できません。
さて、接続情報を環境変数にぶち込みたいのですが、Fly.ioのアプリケーションを用意しないと環境変数を設定できないので先にFly.ioのアプリを用意する必要があります。

### DBにデータをセットする

flyctl経由でDBに接続します。

```
fly postgres connect -a <Postgresアプリケーション名>
```

Postgresアプリケーション名は自分の作成したものに合わせてください。

![Flyioにアプリをデプロイする_2024-01-18-07-57-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/a892414a-4d00-cf4f-bf54-54b8edd5fe74.png)


自分のSpring Bootアプリに合わせて適当にテーブルやレコードをセットアップしましょう。

## Fly.ioアプリをローンチする

Fly.ioアプリケーションを構成していきます。

![](./img/Flyioにアプリをデプロイする_2024-01-17-23-40-34.png)

Fly.ioにはクイックスタートに向けたテンプレート↑がいくつも用意されているが、生憎Javaは含まれていない。

LaravelとかNode.jsとか…。
今回はデプロイするSpring Bootアプリを既に用意しているので、どの道これらには頼らない。

プロジェクトディレクトリ直下で```fly launch``` コマンドを使用するとプロジェクトディレクトリ配下のファイルを解析していい感じにFly.ioアプリケーションを構成してくれる凄い機能があるのだが、Spring Bootアプリ直下で同コマンドを実行してもうまくいかない。Dockerfileとか用意していれば話は別だが。

Fly.ioでは「fly.toml」というファイルにFly.ioアプリケーションの構成を設定する。
```fly launch``` コマンドを実行すればプロジェクトディレクトリ配下の内容と質問の回答によって自動生成してくれるのだが、Spring Bootアプリは未対応。である。っぽい。しらんけど。

Spring Bootアプリを自前でコンテナ化するのは色々と面倒なので、「Cloud Native Buildpacks」を利用する。これはDockerfileを書かずにベストプラクティスに従ってコンテナイメージを生成してくれるツールである。Fly.ioがSpring Bootに対応してくれないので代わりにCloud Native Buildpacksに解析してもらうのだ。

その為には予め「fly.toml」を用意してCloud Native Buildpacksを利用するように設定しておく。


![Flyioにアプリをデプロイする_2024-01-17-23-57-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/4e4cc31f-1cff-dbb5-7939-2805ca565ee7.png)


### fly.tomlファイルを作成する


先ほど用意したSpring Bootアプリのプロジェクトディレクトリ直下に「fly.toml」ファイルを作成する。

```
[build]
  builder = "paketobuildpacks/builder:base"

[build.args]
  BP_JVM_VERSION = "17"
  BPE_BPL_JVM_THREAD_COUNT = "30"
  BPE_DELIM_JAVA_TOOL_OPTIONS = " "
  BPE_APPEND_JAVA_TOOL_OPTIONS = "-XX:ReservedCodeCacheSize=30M -Xss256k"
  BPE_SERVER_TOMCAT_THREADS_MAX = "10"

```

中身は上記のようにしておく。
因みにこの内容は以下のサイトから丸パクリさせて頂いている。
[Fly.ioの無料枠へSpring Bootアプリケーションをデプロイする](https://zenn.dev/backpaper0/articles/3f840d391da4c5) 

JVMのバージョンは自分の環境に合わせて。Java17以外は試してないから知らん。

### fly launchコマンドを実行する

以下のコマンドでFly.ioアプリケーションをローンチする。

```
fly launch
```

![Flyioにアプリをデプロイする_2024-01-18-08-13-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/728a3ec3-bf97-d9f7-d102-6aab00a69f25.png)


なんか知らないけど[build]タグが勝手に削除されたとか言う。
設定をカスタマイズするか聞かれるので```y```で。

![Flyioにアプリをデプロイする_2024-01-18-08-16-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/af5df82c-64a7-cb98-a5fd-c514ec9ad4be.png)


ブラウザが起動し、Fly.ioアプリローンチ用の設定ページが開きます。

- App name：適当で良いです。被らないもの。
- Port：各自のSpring Bootアプリに合わせて。デフォルトなら```8080```。
- VM Memory：```256MB```にしてください。お金かかってもいいなら潤沢なリソースを選んでもいいです。
- Postgres：既に作成済みなので```none```のままでいいです。

![Flyioにアプリをデプロイする_2024-01-18-08-20-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/eec6566c-b2bf-4162-51ff-c4414d83a609.png)


「fly.toml」ファイルが自動的に更新されます。
デプロイされたURLが表示されますのでメモっておきましょう。Fly.ioサイトからも確認できますが。

### 動作確認

先ほど表示されたデプロイ先URLにアクセスしてみましょう。

![Flyioにアプリをデプロイする_2024-01-18-08-22-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/2f7de34e-216d-c394-70fa-21580cca07fa.png)


はい。環境変数を設定していないのでDB接続できません。

### シークレットを設定する。

シークレットは環境変数です。通常の環境変数と異なり、秘匿すべき情報となります。
DB接続情報はGit等に登録したくないのでシークレットで保持しておきます。

![Flyioにアプリをデプロイする_2024-01-18-08-26-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/c2b07069-f03c-e06a-972d-be52582312db.png)



具体的なシークレットを設定するコマンドは以下になります。
設定値は各自のアプリケーションに合わせてください。
PostgresにAPから接続する用のユーザを作成している場合はそちらを使用してください。

```
fly secrets set DATABASE_URL=jdbc:postgresql://<Postgresアプリケーション名>.flycast:5432/postgres?sslmode=disable
fly secrets set DATABASE_USER=<Postgresユーザ名>
fly secrets set DATABASE_PASSWORD=<Postgresパスワード>
```

設定済みのシークレットの一覧は以下で確認できます（値は確認できませんが）。

```
fly secrets list
```

### 動作確認（今度こそ）

再び動作確認してみましょう。

![Flyioにアプリをデプロイする_2024-01-18-08-30-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315984/83ebbc02-bf6d-d617-58b7-f60a521876aa.png)


今度は正常に、DBを検索して結果表示できることが確認できました。

### ログ確認

ログ確認は以下のコマンドで行えます。```tail -f```みたいなイメージ。

```
fly logs
```

### 再デプロイ

アプリに修正が入った場合はデプロイコマンドで再デプロイします。

```
flyctl deploy
```

### 後始末

設定を誤ったリソースを作ってしまったり、不要になったら、余計な課金を招かないためにも削除しておきましょう。
ダッシュボード→アプリを選択→設定→アプリ削除、で消せます。



### さいごに

何か誤っている内容がありましたらご指摘頂けると幸いです。