こんにちは! IMPRICH CREATEのハナミズキです。
これまで業務で色んなWebアプリケーションを開発してきた経験はありますが、そのどれもが業務用の特定の本番環境下に展開していました。
今回、初めてレンタルサーバー「ロリポップ」に、CakePHPを展開したので、デプロイにあたって、整理した結果を忘備録として投稿します。
目次
1.デプロイとは
デプロイとは、開発中のWebアプリケーションを、ユーザーが利用可能な状態にすることです。
デプロイの為には、以下の3つの環境が必要になります。
- 開発環境(ローカル環境)
- ステージング環境
- 本番環境
開発環境(ローカル環境)は、Webアプリケーションの開発を行っている環境であり、非公開環境です。一通り公開しても問題ない状態まで、動作確認や試験を行います。
ステージング環境は、本番環境とほぼ同等の環境を構築したものです。本番環境に公開する前に、本当に設定値に問題がないか、また、公開時にトラブルが発生しないよう、ほぼ同等の環境を作って Webアプリケーションの動作確認をするための環境です。開発者以外の人間も動作検証のためアクセスすることができます。
本番環境は、公開された環境です。不特定の様々なユーザー(もしくはターゲットとするユーザー)から、公式にWebアプリケーションにアクセスできるようにする環境です。ここにWebアプリケーションを配置することで、ユーザーがWebアプリケーションを利用できるようになります。
改めて、デプロイとは基本的に環境構築作業ではあります。作業の流れとして各環境にWebアプリケーションのデータを配置して動作確認します。
2.必要な事前環境構築
開発環境(ローカル環境)から、ロリポップレンタルサーバーに対して、デプロイ連携するために必要な事前環境構築を記載します。
ロリポップは、データをロリポップのサーバーにアップロードに関係する各種ツールについて情報を公開してくれています。
ロリポップ – マニュアル:https://lolipop.jp/manual/
Webアプリケーションデータをロリポップ上のレンタルサーバーへアップロードするのに、FTPクライアントツールを利用します。
また、CakePHP独自のコマンド(例:bin/cakeで始まる各コマンド)をロリポップ上のレンタルサーバー上で実行するには、SSHクライアントツールを利用します。
ここでは、各ツールの用意と設定について共有します。
2-1.FTPクライアントツールの用意と設定
基本的にロリポップのFTPに関するマニュアル( https://lolipop.jp/manual/hp/ftp-set/ )に従います。
なお、ロリポップ「スタンダードプラン」契約時点で、ブラウザから操作可能なFTPクライアントツール「ロリポップ!FTP( https://lolipop.jp/manual/user/ftp2-01/ )」が存在しますが、基本的にこれで十分です。
ただ私の場合、ドラック&ドロップで直感的にファイルのアップロードや、サーバー上のファイルを、開発環境上にインストールしている高性能エディタ(Notepad++)などで軽く修正などもしたかったので、専用のFTPクライアントツール「Cyberduck」を導入しました。
相性もあると思いますが、ロリポップで活用できるFTPツールの解説が丁寧にマニュアルサイト( https://lolipop.jp/manual/hp/ftp-set/ )の「各種FTPソフトの設定方法」の章に記述があります。
改めて、まずは契約情報と共有されているFTPサーバーの情報をロリポップのユーザー専用ページのメニュー「ユーザー設定→アカウント情報」を開き、確認する。
次に、 自分にとって使いやすいFTPクライアントツールをマニュアルに従い指定サイトからダウンロードして、インストールを行う。
あとは、確認したFTPサーバー情報をFTPクライアントツールに登録するだけ。
以上です。
接続時に 「ロリポップ!FTP」接続時と同じように、FTPサーバーのフォルダやファイル情報が閲覧できたら環境構築成功です。
2-2.SSHクライアントツールの用意と設定
基本的にロリポップのSSHに関するマニュアル( https://lolipop.jp/manual/user/ssh/ )に従います。
ロリポップのユーザー専用ページのメニュー「サーバーの管理・設定→SSH」を選択し、SSHを有効にします。
SSHを有効にすると、SSH接続時のサーバー名など情報が表示されます。
ロリポップで活用できるSSHツールの解説が丁寧にマニュアルサイト( https://lolipop.jp/manual/user/ssh/ )の「SSHソフトの設定方法」の章に記述があります。
なお私は、以前業務で活用しなれしていたPuttyを使用しました。
FTPツールの時と同じように、 自分にとって使いやすいSSHクライアントツールをマニュアルに従い指定サイトからダウンロードして、インストールを行う。
あとは、確認したSSHサーバー情報をSSHクライアントツールに登録するだけ。
設定したら、接続すると、ユーザー名とパスワードを求められるので、サイトで確認した情報をもとに入力することでログインできます。
以上で、SSHでコマンドライン操作ができるようになる環境構築が完了です。
今後、デプロイ時に、サーバー上でコマンドライン操作が必要な例は色々とありますが、大前提としてroot権限での操作ができません。
ロリポップのレンタルサーバー上のSSH接続ならではの制限があるため、その制限をよく確認しておくことをお勧めします。
利用可能なコマンドの制限事項はマニュアル ( https://lolipop.jp/manual/user/ssh/ )の「使用可能コマンド一覧」の章に記載されております。
※上記の画像は一部ですが、詳細はサイトを確認してください。
※なお、私は、lnコマンドでシンボリックリンク(ハードリンク)を使いたかったですが、ハードリンクは権限の問題で認められておりませんでした。使用可能なコマンド一覧に記載されていても、一部のコマンド引数は利用できないものがあるため、仕様を意識するときは注意が必要です。
3.CakePHP3のデプロイ手順
CakePHPの公式サイトにデプロイに関する記述があります。
https://book.cakephp.org/3.0/ja/deployment.html
ここでは、以下の順で解説しております。基本はこちらに乗っ取って動きます。
- ファイルの移動
- config/app.php の調整
- セキュリティのチェック
- ドキュメントルートの指定
- アプリケーションのパフォーマンス改善
- 更新のデプロイ
なお、ちょっとした補足ですが、ロリポップスタンダートプランの「PHPモジュール版」では、php.iniの修正ができません。 また、 httpd.conf の修正もできません。
CakePHPのデプロイの「ファイルの移動」の章で記載されている内容を読むと、 本番環境までのデプロイについて一連で説明しています。
具体的には、Gitなどのソース管理ツールを使ったバックアップやクローンの実行、 composer を利用した依存関係の解決など記載されています。
しかし、ロリポップのレンタルサーバー上に、Gitのユーザー設定をするのは、なんか連携部分が増えすぎて嫌…。
また、composerは「ライブラリ依存管理ツール」です。環境構築には必要だけど、本番環境下でWebアプリケーション実行には composer は利用されないので、なるべく実行に関係ないツールは入れたくないです。
よって、私なりに解釈した形でロリポップの公開環境までのデプロイした手順をここに記載していきます。
以下に、その流れを書きます。
( git やcomposerは「ステージング環境」下で動かし、「本番環境」には物理的コピー(アップロード)のみという方針で動きました。 )
3-1.開発環境:バックアップ
Webアプリケーションの開発が終わり、いざデプロイする前に…。
当たり前かもしれないですが、バックアップを取ります。
バックアップには、 基本的にGitで管理しているので、「コミット(commit)」して、リモートリポジトリ(GitHubなど)へ「プッシュ(push)」 を行う事でバージョン管理も含めて完了です。
>git commit -m 'バックアップ時のメッセージを入力'
>git push origin master
上記に、gitコマンドを記載しましたが、実際、普段はコマンドを打つのが面倒なので、TortoiseGitを活用してます。
なお、次のステップに移動する前に、試験を実施します。
試験は、Webアプリケーション専用に「チェックリスト」を作成し、それに従い確認していきます。
この時、重要なものが「セキュリティ」です。
CakePHPのデプロイのページ( https://book.cakephp.org/3.0/ja/deployment.html#id3 )にも記載されておりますが、こちらに記載されている事を意識してコーディングできているか、また、最低でも、SQLインジェクション、XSS、CSRF、ディレクトリトラバーサルなどの攻撃がされても問題ないようなコーディングできているか確認することを忘れないようにします。
試験の結果、バグなどあればバグを修正し、またバックアップをしましょう。
デプロイ前に、ソース上に問題がない形に努力を尽くして必ずしましょう。
なお、基本のCakePHP3プロジェクトのgit無視ファイル(.gitignore)の内容を変更しないまま、Gitを利用してコミット(Commit)すると、tmpフォルダやvendarフォルダ、app.configフォルダなどは、その他、バックアップを取る必要が無い情報は、バックアップされません。
これは、万が一、セキュリティ漏洩事故対策で、データベース情報へのユーザー名やパスワード文字列が含まれたapp.phpなどの設定ファイルを誤って公開ネットワーク上にアップロードしないための無視設定だったりしますので、公開したくない設定ファイルなど「git 無視 設定」が行われているか意識しておきましょう。
3-2.ステージング環境:クローン(複製)
事前にステージング環境を作成する。基本的に本番環境と同レベルの環境設定を行う。今回のロリポップで利用しているPHPのバージョンは7.1ですので、7.1の環境を構築します。
ロリポップの場合、phpinfo()を利用してPHP設定値の確認をできます、そこにはPHP.iniのパスについても記載されているので、実際のphp.iniの内容確認は、sshツールを利用して、中身を読みましょう。
以下の内容が込められたファイルを一時的にロリポップレンタルサーバー上にFTPツールを介して格納する。
<?php
phpinfo();
?>
ロリポップのphpファイルを格納した場所(任意)のURLをアドレスバーに入れて、リクエスト実行するとphpinfo()の結果が確認できます。
上記の段階で、php.iniの内容が確認できるパス情報が見つかるので、sshクライアントにログインして、指定のパスにあるファイルを確認して設定していきましょう。
なお、私の場合、XAMPPを利用して環境を構築しました。Apache系の設定値は見えれないですが、php系の設定だけはなるべく合わせるようにしました。残念な事があるとしたら、現在提供されているXAMPPのPHPのバージョンは、7.1系は、7.1.29しかなかったでした。本来であれば、ステージング環境の為にお金を追加で払って同等の環境を作ることも可能ですが、趣味ツールの挙動確認でもあったので、自身のWindowsPC上で確認できるレベルにし、合わせることができるところを出来る限り合わせました。
そして、
リモートリポジトリ(GitHubなど)から、今回作成したWebアプリケーションをステージング環境下にクローン(複製)・展開します。
>git clone URL ディレクトリ名
この時、重要な設定値(config/app.phpや.env)やWebアプリケーション実行に必要な依存関係のモジュール(vendor/*)はすべて開発環境にのみある状態で、クローン(複製)された事が確認できます。
3-3.ステージング環境:設定ファイル(config/app.php)の調整
開発環境で作成していたconfig/app.phpを、ステージング環境に合わせて新しく作成してください。
以下、本番環境にコピーした時に、そのまま使えるよう設定してください。
- データベースの設定(※1)
- ロケーション設定
- ログ設定
- その他、Webアプリケーションの必要な設定
(※1)既に本番環境が、公に公開されている場合、で、かつ、一時的にデータベースの更新が必要な場合、データベース設定に関しては、ステージング環境専用のデータベースサーバーを用意し、専用のデータベース設定を指定するのが理想です。
3-4.ステージング環境:依存関係の解決
改めて、 Webアプリケーション実行に必要な依存関係のモジュールはすべて開発環境にのみある状態 です。これを解決するために、 composer を利用しましょう。以下コマンドをステージング環境下で実行することで依存モジュールがダウンロードされてきます。
composer install
3-5.ステージング環境:動作確認
動作確認を行う。
各ページのリクエストや、ajaxを使っている場合、ajaxが動くか確認する。
基本的に、細かい試験は開発環境でしっかりと実施済みであるため、ここで行う試験は、設定値に問題が無いかを確認するレベルになります。
ここでソースコードを変更しなければならないレベルの不具合があれば、不具合を修正し、3-1からやり直します。
3-6.本番環境:モジュールの配置
ステージング環境のモジュールを、そのまま何も変更せずに全て本番環境へアップロードします。
本番環境上で、必要な設定変更がある場合は、コピーする前に実施する事。
初回の場合、データベースの構築が必要な場合は、ステージング環境下で用意したのと同じように行う。
また、アクセス権は意識して見直す。
tmpフォルダ、logフォルダのアクセス権を確認してファイルの書き込み出来るよう変更する事。
Cakeシェルを実行するときは、bin/cakeのアクセス権を確認して実行権限を追加しましょう。
3-7.本番環境:動作確認
ステージング環境で確認したのと同じように動作確認を行う。
公開するという事なので、特に念には念を入れるのが重要です。
各ページのリクエストや、ajaxを使っている場合、ajaxが動くか確認する。
基本的に、細かい試験は開発環境でしっかりと実施済みであるため、ここで行う試験は、設定値に問題が無いかを確認するレベルになります。
ここでソースコードを変更しなければならないレベルの不具合があれば、不具合を修正し、3-1からやり直します。
また、本番環境下では、必要に合わせて CkePHPの スキーマキャッシュシェル でキャッシュされた メタデータを削除する場合、SSHツールで接続して、キャッシュクリアを実行します。
この時意識することは、ロリポップには複数のPHPモジュールがインストールされているので、何も考えずにクリアコマンドを実行すると以下のようなになってしまいます。
試しにコマンドphp -v
実行で、PHPのバージョンを確認すると、以下のようにバージョン情報が確認できますが、CakePHPの予定バージョン7.1が出来ようされていない事が
ロリポップのレンタルサーバーでは、PHPのバージョンを5.3、5.4、5.5、5.6、7.1と5種類選べます。phpコマンドの実行すると、5.5が初期として登録されているのが分かりますね。これでは、コマンド実行でPHP 5.5が使われてしまいます。このcakeシェルの実行には、5.6以上、サーバーと環境を合わせるために、7.1が使いたいのが理想です。
よって、bin/cakeを直接修正して、利用するPHPを指定して環境に合わせてコマンドを実行するようにしましょう。
中身を読めばわかりますが、CakePHP3のcake Shellスプリクトの内容は、初期の段階で、PHPという変数が定義されていなければ、関数findCliPhpを呼び出す…。関数findCliPHPでは、”php”という文字列が返却されてくるため、コマンド上「exec php bin/cake.php」というコマンドが実行されるような仕組みで プログラムされています。
コマンド実行時に、php単体で呼び出すと、内部の環境変数パスの影響により、phpのバージョンが5.5になってしまうので、cakeシェル実行時にエラー「5.6以上を使え…」が吐き出されておりました。
今回、ロリポップ提供のPHP7.1を利用したいので、意図的にPHP変数に7.1のPHP実行可能ファイルのパスを定義するよう修正を加えました。(図3-7-3.1つ目の赤枠)
PHP="/usr/local/php/7.1/bin/php"
また、確実に変数の値が置き換わっている事を確認するため、echoでコンソール画面上にパスを吐き出すように修正を加えました。(図3-7-3.2つ目の赤枠)
echo $PHP
その結果、実行すると以下のようにcakeシェルコマンドが実行でき、本番稼働前にキャッシュのクリアできました。
bin/cake cache clear_all
以上で、デプロイ作業完了です。
4.その他(私の環境下で実際に発生した問題)
私の場合、ステージング環境と本番環境を完全に同じ環境(同バージョン、同設定)を作る事が出来ませんでした。
逆にステージング環境と開発環境は、どちらもXAMPPを利用していた影響のため、ほとんど似たような環境だったのもあり、開発環境、ステージング環境では発生しなかった不具合が、ここで発生しました。
指定のリクエストは存在しないというのです。
よって、改めて本番環境上のdebugモードをONにして 動きを確認したら、エラーの詳細が分かりました。
発生したエラーは以下のエラーです。
MissingControllerException toseirekis
トップページは表示されるけど、その後、特定の ToSeirekisController コントローラーを呼び出そうとすると、 Missing ControllerExceptionが発生してしまいました。
基本的に、 MissingControllerException は、CakePHPのコントローラーファイルが存在しないというエラーです。 例えば、リクエストURLを記載する時に、誤字など初歩的な事でエラーが発生します。
最初に確認した事は、指定のコントローラーファイル ToSeirekisController のアップロード洩れが起きていないか確認する事でした。しかし、存在していました。
また、完全に本番環境にアップロードしている状態を再ダウンロードして、ステージング環境とモジュールの差異がないか、差異ツールを使って調査しました。
この時点で、ステージング環境にアップロードしたデータも、本番環境からダウンロードしてきたやつでも、問題が発生していなかったので、アップロード洩れに問題はないと判断しました。
次にURL Rewriting の設定が原因ではないかと疑いました。
なぜならば、ロリポップの、 httpd.conf を修正できない、かつ、実際の設定値の中身を閲覧することができないからです。そこに何か原因があるのではないかと思い、CakePHPのconfig\routes.phpファイルや、.htaccessの内容に問題がないか確認しました。
しかし、事例をもとにネット検索しても、同様の現象に悩んでいる人いませんでした。
各設定値の公式サイトや個人ブログを参考にしながら、設定ファイルの各値とhttpd.confの関係で問題ないかを確認しても、問題は解決しませんでした。
原点回帰として、改めて、エラーメッセージをみました。
MissingControllerException toseirekis
toseirekisControllerが存在しないと言っているので、試しに、 ToSeirekisControllerのファイル名とクラス名をリネームしました。
すると、問題は解決したのです。
なんという事でしょうか。純粋に初歩的なミスだったのです。
ToSeirekisController を呼び出したければ、CakePHP3の命名規約と仕様では、 toseirekis ではなく、to-seirekisと指定しなければいけなかったのです。
問題の記述: src/Template/Pages/home.ctp
$this->Form->create($formEntity, ['url' => ['controller' => 'toseirekis', 'action' => 'index'], 'type' => 'get'])
正しい記述 src/Template/Pages/home.ctp
$this->Form->create($formEntity, ['url' => ['controller' => 'to-seirekis', 'action' => 'index'], 'type' => 'get'])
本来であれば、開発環境でもステージング環境でも、エラーが出てもおかしくない。
なのに、なぜか私の環境では、この誤字は忖度されて、 toseirekis と誤って指定していても、 ToSeirekisController を呼び出してくれていたのです。
この問題は、ソースコードを正しくすることで解決したのですが、また本番環境のみで発生した次のエラーが発生しました。
MissingTemplate
えぇ、先程の事例と近いです。原因は、コントローラーファイル内で以下のように記載していたのが原因でした。
問題の記述
$this->render('/pages/home');
正しい記述
$this->render('/Pages/home');
大文字と小文字だけの問題でした。
そして、この記述は問題が発生しないサーバー環境下では本当に問題が発生しないのです。
むしろ、ロリポップで問題が発生する環境と同等の環境をXAMPPで作りたいけど、設定値をいくら探しても、また見つけることができません。
結果として、問題はすべて解決しましたが、どちらもCakePHP3の規約に沿っていない書き方をしていた初歩的なのが原因でした。
気になることがあるとしたら、確認できるphp.iniの設定に合わせて対応しているはずなのに、XAMPP環境であるステージング環境とロリポップの本番環境で大文字小文字などによって動きが厳密に違う事です。
現在、ロリポップに合わせることができるよう調べ中ですが、Webアプリケーションの動きに関係して、レンタルサーバーと完全に同等の環境を作るのは難しいものですね。ロリポップが今年3月から提供を始めて月々数百円で利用できる専用ステージング環境は、レンタルサーバーと同じ何でしょうかね…?
5.まとめ
改めて、環境は大切です。
今回は、ロリポップでデプロイする方法を調べようと思って簡単なWebアプリケーションを作ってデプロイのやり方を確認しました。
お陰で「念には念を入れる」の大切さを深く実感しました。
本番環境と同等のステージング環境を作る事の大切さ、
もし、作れたとしても、念には念を入れて試験するのは大切です。
今回のデプロイ実験で作ったWebアプリケーションは以下に公開しています。
[GitHub]https://github.com/hanamizuki10/wtos
[App] https://www.imprich-create.site/tools/wtos/
(本当は、このAppのURLを独自で取得したドメイン「www.imprich-create.site」に紐づけたくして、シンボリックリンク作成のSSHコマンドInを使いハードリンクでつなげようとしましたが、ハードリンクの作成はroot権限でしか許可されていなかったのが、最後の心残りです。)
今回のことは、本当に勉強になりました。この忘備録の作成もなかなか時間がかかりましたが、また、いつか悩んだ時の自身の助けにしようと思います。
以上です。ではでは!
この記事へのコメント
コメントはまだありません。