開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. PaaS >
  4. LaravelアプリケーションをFly.ioにデプロイする

LaravelアプリケーションをFly.ioにデプロイする

こんにちは、ナカエです。

Herokuの一件で最近のPaaSの動向が気になり、 Render を始め海外で人気があるPaaSを調査していました。その中の一つが Fly.io です。

flyio_site.png

接続したユーザに最適なデータセンターでアプリケーションを起動することによる低レイテンシ、および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の使い方のドキュメントに飛ばされるだけです。


laravel-fly-io-admin-page.png
 

というわけで、まずはflyctlをHomebrewでインストールし、

brew install flyctl

先ほど作ったLaravelプロジェクトの直下でflyctlのログインコマンドを実行します。

flyctl auth login

自動でブラウザが開くはずなのですが、手元の環境では開かなかったので表示されたURLをブラウザで開いてログインします。

参考 Log in to Fly

ブラウザでログインを確認すると、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が設定されています。これはなかなかの賢さ。

laravel-fly-io-fly-toml.png

# 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


laravel-fly-io-fly-deploy.png

Buildpacksによってビルドされている様子が確認できます。 ローカルでイメージをビルドしてからイメージをFlyへとPushするスタイルのようですね。なるほど。

なお、ローカルにDockerデーモンがない環境でも、Remote buildersという仕組みで対応できるようです。

fly deploy --remote-only

サイトを確認

flyctl open

のコマンドでブラウザで確認できます。 失敗する場合は表示されたURLを手動で開いてください。


laravel-fly-io-laravel-on-fly-io.png
 

レスポンス時間もLaravelのトップページで35ms前後となかなか良好です。

一度アプリをデプロイすると、最初はアプリが1件も表示されていなかった管理画面にアプリが追加されており、アプリの詳細が見られるようになっています。


laravel-fly-io-admin-page2.png
 

料金と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を好む開発者なら大変オススメです。

TOPに戻る