数年前、プライベートウェブサイト用として Heroku にデプロイしてあった Laravel アプリケーションを、今回、Fly.io へマイグレーション(移行)したので、その際に必要になった作業を残しておこうと思います。
Heroku の名前の由来は、 "Hero" と "Haiku" を結合させたものと Wikipedia には説明されていましたが、それは、Heroku の開始当初は Ruby on Rails 用の PaaS だったからです。Fly.io も随所に(英語の)俳句がしたためられていて、私もこの俳句を見てマイグレーション先に Fly.io を選択しました。
自動でマイグレーション(移行)する
まず1つ目は、「Heroku から Fly.io へのマイグレーションには、Fly.io に "Turbocharge" 機能」が用意されている事です。何だかんだで、私は一日がかりでマイグレーションしたのですが、この Turbocharge 機能を知っていれば、ものの数分で終わったかも知れませんでした。
Heroku から Fly.io への自動マイグレーション(移行)機能
PHP と Laravel のバージョンを合わせる
このセクションを読み進めているという事は、冒頭の Turbocharge でマイグレーションできなかったという事だと思います。私が Heroku へデプロイしてあったアプリケーションは、PHP7.2、Laravel/Framework6.2 でした。2023年7月12日現在で、これを PHP8.1、Laravel/Framework10.10 に composer update して、Fly.io へマイグレーションする必要があります。
これを実行するには、まず、PHP8 をインストールします。
上記ウェブサイト等を参考にインストールする訳ですが、私の環境は、Ubuntu 20.04.5 LTS だった為なのか、微妙にバージョンが違っていました。手順を読み替えた部分は、以下の通りです。
sudo apt-get install php8.1-xml
→ sudo apt-get install php8.2-xml
sudo apt-get install php8.1-curl
→ sudo apt-get install php8.2-curl
そして、composer によってインストールされる Laravel/Framework は、10.10 です。
また、「Laravel7 から Laravel8 へのアップデート」を解説されているウェブサイトは多数あるので、それらを参考にアップデートしていきますが、非常に手間が掛かるので、私は、PHP と Laravel のインストールの際に作成する "example-app" の "composer.json" で置き換えて利用しました。アップデートする Laravel アプリケーションは、ローカルに残してあるものや、Heroku にアップロードしてあるものを取得して、手元に用意しておきます。
"example-app" で作成される "composer.json" をマイグレーション対象のアプリケーションの "composer.json" と置き換える。
更に、Laravel7 系と Laravel8 系では、ソースコード上にも非互換箇所があり、その部分はマニュアルで修正する必要があります。
"app/Exceptions/Handler.php" の "Exception" を
→ "Throwable" に変更し、
それに伴い、"use Exception;" も
→ "use Throwable;" に変更する。
namespace App\Exceptions;
use Throwable;
.
.
.
class Handler extends ExceptionHandler
{
.
.
.
public function report(Throwable $exception)
{
parent::report($exception);
}
public function render($request, Throwable $exception)
{
return parent::render($request, $exception);
}
}
また、SMTP を設定している環境変数が変更されています。
".env.sample" (もしくは、".env" )と、"config/mail.php" の
"MAIL_DRIVER" を
→ "MAIL_MAILER" に修正します。
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
/*
|--------------------------------------------------------------------------
| Mail Driver
|--------------------------------------------------------------------------
|
| Laravel supports both SMTP and PHP's "mail" function as drivers for the
| sending of e-mail. You may specify which one you're using throughout
| your application here. By default, Laravel is setup for SMTP mail.
|
| Supported: "smtp", "sendmail", "mailgun", "ses",
| "postmark", "log", "array"
|
*/
'driver' => env('MAIL_MAILER', 'smtp'),
一通り修正が終わったら、"composer update" を実行します。
composer update
npm のバージョンを合わせる
(運が良ければ、)上記修正で PHP/Laravel の "composer update" は完了ですが、Fly.io に launch すると、npm の lock file が古いと "npm WARN old lockfile" を出力してきます。
もちろん、警告がでなければ問題ありませんが、出ている場合は、まず、nvm がインストールされていなければ、nvm をインストールします。
そして、lock file の Warning を解消するために、下記コマンドを実行します。
npm i --package-lock-only
これで、lock file の問題は解消されました。また、node.js の OpenSSL でも "ERR_OSSL_EVP_UNSUPPORTED" エラーが出ているかも知れません。
その場合は、環境変数 "NODE_OPTIONS=--openssl-legacy-provider" を指定して実行するように、どのウェブサイトでも説明されています。Fly.io の場合、単に "export NODE_OPTIONS=..." としても効いていないので、"package.json" で指定します。
package.json にある "scripts" セクションの各行("dev","development","watch"...)に "NODE_OPTIONS=--openssl-legacy-provider" を追加する。
{
"private": true,
"scripts": {
"dev": "NODE_OPTIONS=--openssl-legacy-provider npm run development",
"development": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "NODE_OPTIONS=--openssl-legacy-provider npm run development -- --watch",
"watch-poll": "NODE_OPTIONS=--openssl-legacy-provider npm run watch -- --watch-poll",
"hot": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "NODE_OPTIONS=--openssl-legacy-provider npm run production",
"production": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.19",
"cross-env": "^5.1",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.13",
"resolve-url-loader": "^2.3.1",
"sass": "^1.15.2",
"sass-loader": "^7.1.0"
}
}
デプロイ
こちらも、一通り修正が終わったら、"flyctl launch" を実行します。Fly.io のレジストリがまだの方は、冒頭のリンクなどから登録します。
Fly.io コマンドラインツールのインストールと sign up、そして、アプリケーションの launch。 "flyctl launch" の中では、デプロイまでしてくれます。
curl -L https://fly.io/install.sh | sh
flyctl auth signup
flyctl launch
(幸運にも、)何事もなく正常終了したなら、"flyctl open" でアプリケーションを開始して完了です。
flyctl open
こうして全体を通して概観してみると、"Turbocharge" による自動マイグレーションができない場合は、非常に手間がかかることが、よく解ります。
以上