独り言

プログラミングの講師をしています。新人研修で扱う技術の解説と個人の技術メモ、技術書の紹介など

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で、CentOSMySQLなので、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の設定は移行する前に事前に実施しておく。
そしてサーバー移行のタイミングで

  1. Herokuをメンテナンスモードにする
  2. データベースのバックアップをとってデータ移行
  3. 移行先環境で軽く動作確認
  4. 移行元のプログラムの修正と反映
  5. メンテナンスモードの解除

という感じです。