LaravelアプリケーションをFly.ioにデプロイする
こんにちは、ナカエです。
Herokuの一件で最近のPaaSの動向が気になり、 Render を始め海外で人気があるPaaSを調査していました。その中の一つが Fly.io です。
接続したユーザに最適なデータセンターでアプリケーションを起動することによる低レイテンシ、およびflyctlというCLIのコマンドで完結できるというところがウリのようです。
In the process we want to make application distribution platforms as ubiquitous as CDNs.
アプリケーション配布プラットフォームをCDNと同じくらいユビキタスにしたい、とのこと。
今回はそんなFly.ioに例によってLaravelアプリケーションをデプロイしていきます。
検証環境とソフトウェアのバージョン
- OS: macOS Monterey 12.2.1
- CPU: Intel Core i5
- zsh 5.8
- PHP 8.1.5
- Laravel 9.10.1
- flyctl 0.0.325
作業の前に、Fly.io のアカウントを作成し、支払い情報を登録しておきます。
Laravelアプリを作成
下記コマンドで新規Laravelアプリを作成します。
composer create-project laravel/laravel laravel-fly-io
Cloud Native Buildpacks向けのイメージビルド設定
Fly.ioはCloud Native Buildpacksにも対応しているので、DockerfileではなくCNBで試したいと思います。
作成・変更するファイルは 以前のCloud Native Buildpacksの記事 とほぼ同じで、HerokuのBuildpackを利用します。
Procfile
web: heroku-php-nginx -C nginx.conf public
nginx.conf
location / {
try_files $uri @rewriteapp;
}
location @rewriteapp {
rewrite ^(.*)$ /index.php$1 last;
}
project.toml
※ flyctlは現状project.tomlを読んでくれないのでなくても動作はするのですが、ローカルでのPack CLIによる環境再現用に用意しておくと良いです。 参考: 独自でProjectDescriptorを作ってしまっているflyctlのソースコードの該当箇所
[project]
id = "laravel-fly-io-test"
name = "Laravel Fly.io Test"
version = "1.0.0"
[build]
exclude = [
"/README.md",
"/.git",
"/vendor",
"/node_modules"
]
builder = "heroku/buildpacks:20"
[[build.buildpacks]]
uri = "heroku/php"
[[build.buildpacks]]
uri = "heroku/procfile@1.0.1"
[[build.buildpacks]]
uri = "heroku/nodejs"
.dockerignore
※ なぜかproject.tomlのexclude相当の設定値を.dockerignoreから読んでくるようなので追加します。
参考: .dockerignoreからproject.tomlのexclude相当の情報を取ってくるflyctlのソースコードの該当箇所
/README.md
/.git
/vendor
/node_modules
package.json
{
"name": "laravel-fly-io",
"private": true,
"engines": {
"node": "16.x"
},
"scripts": {
// 略
"heroku-postbuild": "npm run production"
},
// 略
}
Fly.ioの設定
CLIからの操作を前提としているため、Fly.ioの管理画面はここからアプリ作成の操作は行わないよという意志を感じさせます。 右上のCreate appボタンを押してもFlyctlの使い方のドキュメントに飛ばされるだけです。
というわけで、まずはflyctlをHomebrewでインストールし、
brew install flyctl
先ほど作ったLaravelプロジェクトの直下でflyctlのログインコマンドを実行します。
flyctl auth login
自動でブラウザが開くはずなのですが、手元の環境では開かなかったので表示されたURLをブラウザで開いてログインします。
ブラウザでログインを確認すると、CLIのほうでも successfully logged in as {メールアドレス}
のように表示されます。
以下は Deploy Your Application via Dockerfile を参考に作業を進めていきます。
flyctl launch
対話形式で設定を行うと、fly.tomlが生成されます。今回は下記のように設定しました。
- App Name: laravel-fly-io
- Region: nrt(Tokyo Japan)
- PostrgreSQLのデータベース: 作成しない
- 今すぐデプロイ: しない
fly.tomlは下記のようになっており、CNBを使いたい気持ちが通じたようです。 builderのHerokuのBuildpacksが設定されています。これはなかなかの賢さ。
# fly.toml file generated for laravle-fly-io on 2022-05-01T11:32:20+09:00
app = "laravle-fly-io"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[build]
builder = "heroku/buildpacks:20"
[env]
PORT = "8080"
[experimental]
allowed_public_ports = []
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
fly.tomlについてのドキュメント App Configuration(fly.toml) # The build Section を見ると、buildのセクションのbuilderでCNBのBuilderを指定できることが確認できます。
ただし、project.tomlを読んでくれないので、ここにもbuildpacksの設定を追加します。
// 略
[build]
builder = "heroku/buildpacks:20"
buildpacks = [
"heroku/php",
"heroku/procfile@1.0.1",
"heroku/nodejs"
]
// 略
環境変数設定
環境変数は設定ファイルに記述できます。 fly.tomlにLOG_CHANNELの設定を追加します。
fly.toml
[env]
PORT = "8080"
+ LOG_CHANNEL = "stderr"
Secrets and Fly Apps のドキュメントにあるように、シークレットを設定することもできます。
せっかくなので、もう一つの環境変数APP_KEYはこちらの方法で設定してみます。
flyctl secrets set APP_KEY={ローカルの.envのAPP_KEYから値をコピー}
設定したシークレットはコマンドで確認できます。
$ fly secrets list
NAME DIGEST DATE
APP_KEY 739b065f51d4e0e469d31cb2de664ac0 19s ago
デプロイ
準備が整ったのでデプロイします。
flyctl deploy
Buildpacksによってビルドされている様子が確認できます。 ローカルでイメージをビルドしてからイメージをFlyへとPushするスタイルのようですね。なるほど。
なお、ローカルにDockerデーモンがない環境でも、Remote buildersという仕組みで対応できるようです。
fly deploy --remote-only
サイトを確認
flyctl open
のコマンドでブラウザで確認できます。 失敗する場合は表示されたURLを手動で開いてください。
レスポンス時間もLaravelのトップページで35ms前後となかなか良好です。
一度アプリをデプロイすると、最初はアプリが1件も表示されていなかった管理画面にアプリが追加されており、アプリの詳細が見られるようになっています。
料金とDB周り
Fly App Pricing を見ると、Fly.ioの無料枠は割と太っ腹な感じがします。 特にVMはメモリ256MBのVMが3台分となっています。
VMが完全に従量課金で定額が設定されているPaaSに比べると少し怖いか?と思いましたが、デフォルトでは Auto Scaling は無効のようなので、試していたら知らないうちに課金額が膨れ上がったということはなさそうです。
また、今回はDBは設定していませんが、Multi-region PostgreSQL のドキュメントを見るとをPostgreSQLをマルチリージョンで設定することが可能なようです。価格も $6.88/mo
からとお手頃。最近流行りのSQLiteと Litestream を使うという選択肢もありえるでしょう。
Redisは自前のコンテナで立ててくれというスタイル(参考: Redis on Fly)のようですね。できればRedisもマネージドサービスが欲しいですが、色々技術的にも難しそうな匂いがします。
まとめ
Buildpacks周りの設定で一部引っ掛かるところがありましたが、flyctlは総合的に気が利いていて快適な使い心地でした。 CLIを好む開発者なら大変オススメです。