Herokuで構築したシステムをCentOS8環境に移行した時の作業ログ
無料で使えるPaasのサービスであるHerokuにPHPを使ったシステムを構築していましたが、さくらのVPSを契約してCentOS8環境に移行したので、その時の手順をまとめます。
移行前の環境
- サーバー環境:Heroku
- DB:PostgreSQL(Heroku Postgres)
- 言語:PHP
概要
システムの概要は本筋と関係ないので省略。
PHPで作成したWebアプリケーションをHerokuのフリープランの中でデプロイして稼働。
DBはHerokuのサービスの中で無料で使用することができるHeroku Postgresを使用。
移行後の環境
移行しようと思った背景
稼働時間の解決
Herokuのフリープランだと、初回アクセスに時間がかかる。
初回アクセスから30分は通常通りに動作するが、また30分たつと初回アクセスが遅くなる。
dynoというHerokuのコンテナが、起動するときに多少時間がかかるのだが、フリープランだと、基本的にはdynoは起動しておらず、アクセスされて初めて起動。
その後アクセスし続ければ遅くなることはないが、30分アクセスがなければ自動でまた停止してしまう。
解決するためには定期的にcurlコマンドなどでリクエストを投げれば解決できる。
cronとかタスクスケジュールでローカルのPC定期的から定期的にリクエスト投げれば良いが、ローカルのPCの電源が付いている必要がある。
また、Herokuのフリープランではトータル稼働時間に制限がある。(確か600時間くらい)
クレジットカードを登録することで無料のままでもトータル稼働時間は伸ばせる。 ただ、1つのシステムだけ稼働していれば十分対応できるが、システムを2つ以上稼働させようと思うとフリープランでは厳しい。ドメインの取得
自分でサーバーを構築、ドメインの取得をすれば、サブドメインとバーチャルホストの機能を使うことで、1つのサーバーで複数のシステムを構築することができる。DBの統一
HerokuだとアプリケーションごとにDBを作成する必要があるし、レコード件数に縛りがある。
自分でサーバー構築したら、複数のシステムがあってもDBを1つにできるしレコード数の制限もない。httpsにしたかった
個人情報の入力やログイン処理などがあるが、Herokuではスキームはhttpになっている。
Herokuでもhttpsにすることはできるみたいだが、聞いた話少々面倒らしいので、自分でサーバーを構築した方が手っ取り早そうだった。Linux上で色々遊ぶことができる
CentOS8上で構築できるので、システムの動作環境以外でも色々Linux絡みの勉強やお試しができる。
移行時に注意するべきこと
- DB環境
Herokuの環境はPostgreSQLで、CentOSはMySQLなので、DBの違いに注意。
CentOSでもPostgreSQLをインストールすることもできるが、さくらのVPSだと起動時のスクリプトでLAMPのインストールがある。
PHPのシステムなのでLAMPで楽したかったのでMySQLにした。
ただ、ローカルの開発環境はXAMPPとかMAMPを使ってたので、MySQLでもPostgreSQLでも適応できるSQLで開発してたので問題なし。
いざ実行
前置きはこれくらいにして実際の作業手順に付いて。
1. Herokuをメンテナンスモードに
まずは移行元となっているアプリケーションを使用できない状態にする必要がある。
Herokuにはメンテナンスモードというのが用意されており、コマンドでサクッと切り替えられたので、それを使用。
heroku maintenance:on --app アプリ名
これでメンテナンスモードになり、システムが使用不可になる。
2. DBのバックアップの取得
続いてはheroku postgresからDBのバックアップの取得をする。
まずはconfigの情報からデータベースの情報を取得。
heroku config:get DATABASE_URL --app アプリ名
結果、こんな感じのが返ってくる。
postgres://pxxsmjadcejqnv:8a68cb4f3e311442d688439ea25d780f7e580d0263da70afe65181f20c1a705b@ec2-174-129-255-15.compute-1.amazonaws.com:5432/dd2fk9n2pggjn7
これは
postgres://ユーザー名:パスワード@ホスト名:ポート/DB名
となっている。
それを踏まえてpg_dumpコマンドを使ってバックアップを取得する。
※ローカル環境にpostgresqlがインストールされている前提です。じゃないとpg_dumpコマンドが使えない。
Heroku上でもDBのバックアップは取得可能。
ただし、バイナリ形式になっている。
MySQLに移行するためにはinsert文でデータが欲しいので、pg_dumpを使って取得する。
pg_dump -d DB名 -h ホスト名 -U ユーザー名 --column-inserts -W > database.sql
--column-insertのオプションをつけないと、インサート文の形式ではなくなる。
insert文の形式にすると処理に時間がかかるらしいので、postgresqlに対しての移行ならオプションはつけない方が良いでしょう。
今回は移行先のDBが異なるのでinsert文にした。
3. SQL文を実行する
テーブルを作成するSQL文に関しては、開発時点で作成済みなので、移行先の環境にも既にスキーマやテーブル、インデックスなどは作成済み。
なのでインサート文のみ実行。
注意点としては、各テーブルの主キーはidで自動採番にしていたので、その点の考慮が必要。
PostgreSQLだとserial、MySQLだとauto_increment
ただ、最近はMySQLでもserialが使える(内部的にはauto_incrementとして処理しているだけらしいが)
ので、テーブル作成のcreate文はserialにしてればそのまま活用可能。
ただインサート後にauto_incrementの数値を更新するSQLを作成する必要がある。
postgreSQLのバックアップにserialのデータの更新があったので、その数値を参考にauto_incrementの更新を作成して実行。
ALTER TABLE xxxx AUTO_INCREMENT=100;
インサート文は特にエラーも起きず、問題点はなかった。
4. プログラムの移行
プログラムのソースコードはGitHubで管理していたので、移行で特に困ることはなかった。
さくらのサーバーにあらかじめGitがインストールされていたので、それを使ってClone及びプルする感じ。
DBの接続先をMySQLにして、サーバーのMySQLのパスワードに変更。
デフォルトだとrootユーザーしかなく、パスワードが設定されていないので、必要に応じてユーザーを作成してパスワードを設定して、接続URLを合わせてソースコードを修正。
また、作成したデータベースに対して接続するユーザーからのアクセス権限をつけないと、プログラムからアクセスできないので注意。
grant all on opencourt.* to root@'localhost';
プログラムでエラーが出た時には
/avr/log/php-fpm/www-error.log
の中にあるので、動作確認でエラーが出る場合はこちらを参照。
なんか、json_encodeの関数でエラーが出たりする現象があった。
jsonのライブラリがインストールされてなかったみたい。
https://zafiel.wingall.com/archives/10521
ここを参考にインストールした。
5.サブドメインとバーチャルホストの設定
サーバーを移行した一番の目的がこれ。
ドメインを取得して、サブドメインとバーチャルホストを使うことで、一つのドメインで複数のシステムを同時に公開することができる。
サブドメインの設定方法は下記のサイトを参考にした。
http://monopocket.jp/blog/it_others/2457/
送信ボタンを押すまで反映されないことに注意。
Apacheのバーチャルホスト用の設定ファイルが必要。
/etc/httpd/conf.d/
の中に、なんでもいいので拡張子が.confのファイルを作成する。
vhost.confとかvirtualhost.confとかにするのが一般的っぽい。
書き方は適当にネットで検索してそれっぽいのを探す。
書き方が間違っていなければ、apacheの再起動でうまくいく。
6. SSLの設定
Herokuの時にはhttpsにしてなかったので、移行ついでにSSLの設定も実施した。
最初は、一番安い有料のSSL証明書を購入して
https://qiita.com/yoshizaki_kkgk/items/e6f39a5bfb99900b44b2
ここを参考にやってみた。
※vhost.confの中に「Listen 443」の行があるが、これがあるとサーバー起動でエラーになるので注意。
また、認証ファイルの配置方法についてはメールの案内に従った方が確実。
手順通りでSSLにすることはできたが、どうやらサブドメインに対応してなかった。。。
よくよく調べてみると、サブドメインに対応するにはワイルドカード型という証明書である必要があるらしい。。。
ただ、ワイルドカード型は値段が高価。
ということで断念。
色々調べていると、無料で使えるSSL証明書で「Lets Encrypt」というのがあるらしい。
https://knowledge.sakura.ad.jp/10534/
それを使うことにした。
上記の情報は色々バージョンが古かったので、CentOS8で新しいバージョンに対応しているもの
https://www.server-world.info/query?os=CentOS_8&p=ssl&f=2
ここを参考にした。
最終的にはこんな感じにコマンドで、サブドメインに対してSSLを対応させることができた。
certbot-auto -w /var/www/html -w /var/www/html/aaaa -w /var/www/html/bbbb -d eventmanc.com -d aaaa.eventmanc.com -d bbbb.eventmanc.com
ただ、SSLの有効期限はデフォルトでは3ヶ月らしい。
有効期限が1ヶ月を切ったタイミングで
certbot-auto renew
コマンドを入力すると期限をリセットできるらしい。
しかし手動で打つのは面倒なので、cron使って毎日夜中に自動でコマンドが入力されるように更新する。
crontab -e # 中身 0 3 * * * root /usr/bin/certbot-auto renew
7. Heroku環境のプログラムの修正
システム移行後は移行前のシステムでデータを登録されても困るので、使えないようにする。
.htaccessを設定して、index.php(index.html)にしかアクセスされないようにする。
そのページでは、新しいシステムのURLの案内を書いておく。
内容に問題なければ、メンテナンスモードを解除する。
heroku maintenance:off --app アプリ名
まとめ
手順として1〜7まで書きましたが、実際には4, 5, 6のプログラムの移行、サブドメインとバーチャルホストの設定、SSLの設定は移行する前に事前に実施しておく。
そしてサーバー移行のタイミングで
- Herokuをメンテナンスモードにする
- データベースのバックアップをとってデータ移行
- 移行先環境で軽く動作確認
- 移行元のプログラムの修正と反映
- メンテナンスモードの解除
という感じです。