|||||||||||||||||||||

なんぶ電子

- 更新: 

Laravelのデプロイ

LaravelをデプロイするためにPHPをBuildした様子

かつてLaravelの開発環境を設定していろいろ学んできましたが、いよいよデプロイです。

Windows10で開発したLaravel9のプロジェクトをDebian11にデプロイしました。Laravelのデプロイは基本的にはプロジェクト単位でコピーをして設定を変更するだけなのでさほど難しくはないものです。

ただLaravel9がPHPのバージョン8.0以上を要求しているのに対し、執筆時点のDebian11においてはAPTで取得できるPHPのバージョンは7.4だったので、apacheとPHPをmakeすることになりましたが、こちらの方法については別記事DebianでApacheとPHPをビルドを参考にしてください。

Laravelプロジェクトのデプロイ

Apache と PHPの環境が整ったら、本番サーバーにLaravelプロジェクトをデプロイします。

サーバーにcomposerがない場合はリンク先を参考にインストールします。

# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
# php composer-setup.php
# php -r "unlink('composer-setup.php');"

作業後に作業ディレクトリ「composer.phar」という名前で実行ファイルができます。これは後からオートローダ―を最適化する際に利用します。binディレクトリなどパスの通った場所から、composerというシンボリックリンクを張ります。

同様にNode.js環境もインストールします。Node.jsのインストールはNVMを使って行うのがいいと思います。

LinuxにおけるNVMは実行したユーザーのホームディレクトリに.nvmとして保存されます。実行ファイルへのパスはスクリプトが.bashrcファイルに記述してくれますが、初回時はうまく反映されていないことがあります。which nvm等の応答がなかったら再ログインしてみてください。またroot環境でインストールしてしまうと、ユーザー環境からは利用できない場所にインストールされてしまいますので注意が必要です。

$ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
$ nvm install --lts
$ nvm use インストールされたバージョン

nvmをアンインストールしたい場合は.nvmディレクトリを削除するだけです。npmの実行ファイルは.nvmディレクトリの下流にありますが、エラーログ等はユーザーディレクトリ内の.npmディレクトリに保存されるようですので、nvmアンインストール時にはそれも削除します。

この後の手順は次のようになります。

  1. ファイルのコピー

    基本的にプロジェクトディレクトリをコピーします。「/node_modules,/public/build,/storage/*.key,/vendor,.phpunit.result.cache」など通常.gitignoreに含まれるディレクトリ以外のすべてが対象となります。

    後々のことを考えるとgitを利用して開発側でアップロードしたgitレポジトリを本番側でcloneした方が便利だと思いますが、この時デフォルトだと、.envファイルは含まれないので別途生成するかコピーします。また、composerやnodeで設定したパッケージもコピーされませんので、それぞれ「npm update」「composer install」を実行します。

    コピーしたファイルとディレクトリの所有権はこのあとcomposerやnpmを実行するユーザーにしておきます。

  2. APP_KEYの再生成

    .envファイルに設定してあるAPP_KEYを生成または再生成します。

    $ php artisan key:generate   
    
  3. 環境をプロダクションモードに

    .envファイル中の「APP_ENV」の値を「local」から「production」にします。

  4. デバッグモードの解除

    .envファイル中の「APP_DEBUG」の値をfalseにします。APP_ENVの後に出現する設定なのでここで紹介していますが、この値をfalseに設定すると実行時に詳細なエラーメッセージが出なくなりますので、稼働を確認してからの方がいいかもしれません。

  5. APP_URLの設定

    デフォルトでapp.testとなっているURLを正規のものに変えます。

  6. データベースの設定

    初回のデプロイ時は環境によってデータベースにユーザー登録等が必要になります。またマイグレーションやシードも必要に応じて実行します。

    bootstrapに相当する場所(サービスなど)にデータベーステーブルが存在することが前提のコードが書かれていると、例外がスローされてphp artisanコマンドを実行できない場合があります。コードを直すか、それが難しければ開発側のデータベースのテーブルをダンプしたものを本番側でインポートします。MySQL(MariaDB)におけるダンプ・インポートの方法は次の通りです。

    $ mysqldump -u ユーザー名 -p データベース名 --default-character-set=binary>dump.sql
    
    $ mysql-u ユーザー名 -p データベース名 --default-character-set=binary<dump.sql
    
  7. JavaScriptのビルド

    JavaScriptの環境自体は既に設定済みだと思いますので、ビルドのコマンドを実行するだけです。buildしてから本番環境にコピーする方法も試してみたのですが、やり方が悪かったのか@viteディレクティブが本番環境にならずうまくいきませんでした。

    $ npm run build
    

    ビルド時に、次のようなエラーが出た場合はstack overflowを参考に、/etc/sysctl.confのファイルウォッチャーの制限を変更します。

    System limit for number of file watchers reached

    /etc/sysctl.conf

    ...
    fs.inotify.max_user_watches = 16384
    ...

    ここで設定した値は適当です。筆者の環境ではデフォルト値が8192だったので倍にしました。変更後、「sysctl -p」で設定を反映させます。

  8. オートローダの最適化

    Composerのクラスオートローダの最適化をします。ここで先ほどインストールしたcomposer.pharを使います。composerは管理者権限で実行すると警告がでます。

    $ composer.phar install --optimize-autoloader --no-dev
    
  9. configの最適化

    構成ファイルをひとつのキャッシュファイルにまとめます。新しい環境でconfigのキャッシュしないと古い環境のものが使われてしまい、思わぬエラーに悩まされることになります。

    $ php artisan config:cache
    
  10. ルートの最適化

    すべてのルート登録をキャッシュ ファイル内の 1 つのメソッド呼び出しに減らします。

    $ php artisan route:cache
    
  11. ビューの最適化

    すべての Blade ビューをプリコンパイルします。

    $ php artisan view:cache
    

すべて終えたら、エントリーポイントであるpublicディレクトリ内のindex.phpにアクセスして意図したように表示できるかチェックします。

開発環境がWindowsでデプロイはLinuxという場合は、ファイルの大文字と小文字の違いが識別されるようになる上に権限の概念も加わりますので注意が必要です。

筆者が実際に遭遇した事例を挙げると、はphp artisanコマンド等でautoload_real.phpのコードでエラーとなって何もできなかったのですが、composer.jsonのautoload上のパスの中のappのaが大文字になっていました。

...
"autoload": {
  "files": [
     "app/helpers/CustomHelper.php"
  ]
},
...

ちなみにこれは自作のヘルパー関数を追加する設定だったので、値の修正後は「composer dump-autoload」を実行してautoloaderを更新することも必要です。

細かな設定

稼働が確認できたら細かな設定をします。

htdocs以下のファイルやディレクトリの所有権の設定の仕方はいろいろな考え方があるとは思いますが、stack overflow:「How to set up file permissions for Laravel?」に答えのひとつがありました。

ただ先のサイトのまま従ってしまうと、本番環境でnpm run buildが実行できなくなってしまいます。なので筆者は次のようにしました。

  1. ファイルのコピー

    筆者の環境のumaskの値は0022です。

  2. 「composer install」「npm update」を実行
  3. 所有権を、編集ユーザー:apacheグループに変更
    # chown -R edit-user:www-data プロジェクトdir/
  4. すべてのファイルから「その他」の書き込み権限と実行権限を削除
    # find プロジェクトdir/ -type f | xargs chmod o-wx
  5. すべてのディレクトリから「その他」の書き込み権限を削除
    # find プロジェクトdir/ -type d | xargs chmod o-w
  6. すべてのファイルに「グループ」の書き込み権限を追加
    # find プロジェクトdir/ -type f | xargs chmod g+w
  7. すべてのディレクトリに「グループ」の書き込み権限を追加
    # find プロジェクトdir/ -type d | xargs chmod g+w

そのほかphp.iniを修正してエラーの出力と止めたり、apacheの設定でディレクトリ指定時のファイルのリストを止めたりします。

apacheのhttpd.confのdir_moduleを使って、publicディレクトリにアクセスした際にindex.phpを表示させようとすると、次のようなエラーになりうまくいきませんでした。

The GET method is not supported for this route. Supported methods: HEAD, POST, PUT, PATCH, DELETE, OPTIONS.

それに対する回避策は、index.htmlファイルを作ってidnex.phpにリダイレクトするようにするのが簡単です。

index.html

...
<head>
<!-- metaで書くパターン-->
<meta http-equiv="refresh" content="0;URL='./index.php'"/>

<!-- jsで書くパターン-->
<script>
  window.onload = function () {
    location.replace("./index.php");
  };
</script>

ただ、他に設定しなければならないものもありますので、.htaccessファイルとmod_rewriteを使って次のようにするのがいいと思います。

.htaccessファイルを利用するために、httpd.confでは設定の上書きを許可します。同時に、ファイルのリストの出力をやめ、mod_rewriteを有効にします。

httpd.conf

...

# mod_rewriteを有効に(コメントアウトを外す)
LoadModule rewrite_module modules/mod_rewrite.so

...
<Directory "/usr/local/apache2/htdocs">
...
  # Indexesを消してファイル一覧を出さないようにする
  Options FollowSymLinks
  
  # NoneからAllに変えて設定の上書きを許可する
  AllowOverride All
  
</Directory>

プロジェクトディレクトリ直下のデータを読み込まれるのはよくないので、下流のディレクトリを参照できないようにします。

プロジェクトデイレクトリ/.htaccess

...
<Files "*">
  deny from all
</Files>

publicディレクトリだけは例外に指定します。プロジェクトのpublicディレクトリにはLaravelが生成した.htaccessファイルが存在しますので、それに追記します。

ここにルートアクセスの際のリダイレクトも追加します。

プロジェクトデイレクトリ/public/.htaccess

...
<IfModule mod_rewrite.c>
  <IfModule mod_negotiation.c>
    Options -MultiViews -Indexes
  </IfModule>

  RewriteEngine On

  # Handle Authorization Header
  RewriteCond %{HTTP:Authorization} .
  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

  # Redirect Trailing Slashes If Not A Folder...
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} (.+)/$
  RewriteRule ^ %1 [L,R=301]

  # Send Requests To Front Controller...
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^ index.php [L]

  # pulicディレクトリアクセス時のリダイレクト設定
  RewriteRule ^$ %{REQUEST_URI}index.php [L,R]
</IfModule>

# ファイル読み込み例外設定
<Files "*">
 allow from all
</Files>

参考にさせていただきましたサイトの皆様、ありがとうございました。

筆者紹介


自分の写真
がーふぁ、とか、ふぃんてっく、とか世の中すっかりハイテクになってしまいました。プログラムのコーディングに触れることもある筆者ですが、自分の作業は硯と筆で文字をかいているみたいな古臭いものだと思っています。 今やこんな風にブログを書くことすらAIにとって代わられそうなほど技術は進んでいます。 生活やビジネスでPCを活用しようとするとき、そんな第一線の技術と比べてしまうとやる気が失せてしまいがちですが、おいしいお惣菜をネットで注文できる時代でも、手作りの味はすたれていません。 提示されたもの(アプリ)に自分を合わせるのでなく、自分の活動にあったアプリを作る。それがPC活用の基本なんじゃなかと思います。 そんな意見に同調していただける方向けにLinuxのDebianOSをはじめとした基本無料のアプリの使い方を紹介できたらなと考えています。

広告