DeployerでLaravelをrsyncデプロイ – Xserverへの効率的な公開設定

by

カテゴリー:

LaravelプロジェクトをレンタルサーバーのXserverへ、安全かつ効率よくデプロイするために、PHP製のデプロイツール「Deployer」を使っています。この記事では、ローカルでビルドした成果物を rsync でサーバーへ転送する構成を、deploy.php の完成例つきで解説します。Git経由デプロイとの違い、shared / writable 設定、.env・storage・bootstrap/cacheの配置、migrationやqueue再起動、rollback、そしてXserver特有のSSH・PHPパス・権限のハマりどころまで、この記事の設定例だけで初回デプロイを再現できることを目指しています。

デプロイ全体の流れ(Deployer導入〜初回デプロイ)

細かい設定に入る前に、Deployerを導入してから初回デプロイが完了するまでの全体像を先に押さえておきます。

  1. Deployerを導入する:ローカルのLaravelプロジェクトに composer require --dev deployer/deployer でインストールする
  2. XserverのSSHを有効化する:サーバーパネルでSSH設定をオンにし、公開鍵を登録する(ポートは 10022
  3. deploy.php を用意する:後述の完成例をベースに、ホスト名・ユーザー・パスを自分の環境へ書き換える
  4. サーバー側に .env を配置するshared/.env として本番用の環境設定を置く
  5. 初回デプロイを実行する./vendor/bin/dep deploy stg でステージングへ、問題なければ prod
  6. 公開ディレクトリをシンボリックリンクする:Xserverの公開ディレクトリから current/public へリンクを張る

以下ではこの流れに沿って、実際に使っている設定を分解して説明します。

現在地点

以前に、以下の記事を書きました。

レンタルサーバーにLaravelをデプロイするDeployerの使い方

こちらの記事ではDeployerを使用したシンプルなデプロイ方法を紹介しています。

記事内では「レンタルサーバー環境でnodeのビルドを行いましょう」と紹介していますが、なにぶん古い記事なため、node.jsの必要バージョンがv20系と新しい物にしないとビルドが出来ないのですが、v20系のnodeが動かないという問題が発生していました。

node.jsの実行エラー解消「version `GLIBC_2.27′ not found」

今まではv16系で対処していたのですが、重い腰をあげて対応したのが今回の記事につながりました。レンタルサーバー内でnodeのビルドはせずに、ビルド結果のjsファイルをまとめてrsyncでデプロイする事にしました。

Deployerとは?

Deployer はPHPアプリケーション向けのデプロイツールで、SSH経由でサーバーへのコード転送や、キャッシュクリア、ロールバックなどを自動化できます。

Laravelとの親和性も高く、recipe/laravel.phpを利用することで composer install・migration・各種キャッシュ生成・storage:link といったLaravel特有の処理を最初から組み込んだ状態でデプロイできます。導入はローカルのLaravelプロジェクトで次のコマンドを実行するだけです。

composer require --dev deployer/deployer

今回の構成

  • デプロイ先のサーバー:Xserver(SSH接続可)
  • PHPバージョン:8.2
  • Laravelアプリケーション
  • デプロイ方式:ローカルでnpmビルド → rsync転送
  • 環境:本番(prod)とステージング(stg)の2つ
  • バージョン:”deployer/deployer”: “^7.5”,

rsyncを使う理由とGit経由デプロイとの違い

Deployerの標準的なデプロイ(recipe/laravel.phpdeploy:update_code)は、サーバー上で git clone / git pull を実行してソースを取得します。これに対して今回はサーバー側のgit取得を無効化し、ローカルでビルドした成果物を rsync で転送する方式に切り替えています。

rsyncでデプロイする利点は次のとおりです。

  • GitHubなどからソースを取得するためのデプロイキー(秘密鍵)をレンタルサーバー内に置かないで済む
  • nodeのソースインストールなど、レンタルサーバーでの事前準備が不要になる(ビルドはローカルで完結)
  • 差分のみ転送されるため、2回目以降の転送が速い

Git経由デプロイとの違いを整理すると次の表のようになります。

観点Git経由デプロイrsyncデプロイ(本記事)
ソース取得サーバー上で git clone/pullローカルから rsync で転送
ビルド(npm等)サーバー上で実行ローカルで実行し成果物だけ転送
サーバーの事前準備git・node・npmが必要SSHとPHPがあればよい
秘密情報デプロイキーをサーバーに配置サーバーに鍵を置かない
向いている環境自由に環境構築できるVPS等Xserver等の制約が多いレンタルサーバー

Xserverのように、GLIBCのバージョンが低くて新しいNode.jsが動かない環境では、rsync方式のほうが圧倒的に扱いやすくなります。

deploy.php の完成例

まずは全体像として deploy.php の完成例を掲載します。この1ファイルで初回デプロイまで再現できます。各設定項目はこのあとのセクションで分解して説明します(ホスト名・ユーザー名・パスはご自身の環境に置き換えてください)。

<?php

namespace Deployer;

require 'recipe/laravel.php';
require 'contrib/rsync.php';

// ---- 基本設定 ----
add('shared_files', ['public/.htaccess']);
set('keep_releases', 3);
set('bin/php', '/usr/bin/php8.2');
set('bin/composer', '/usr/bin/php8.2 ~/bin/composer.phar');

// ---- 共有 / 書き込み権限(recipe/laravel.php の既定に追記する場合)----
add('shared_dirs', ['storage']);
add('shared_files', ['.env']);
add('writable_dirs', ['bootstrap/cache', 'storage']);
set('writable_mode', 'chmod');   // Xserverは sudo 不可
set('writable_use_sudo', false);

// ---- rsync 設定 ----
set('rsync_src', __DIR__);
set('rsync_dest', '{{release_path}}');
set('rsync', [
    'exclude' => [
        '.git',
        'deploy.php',
        'node_modules',
        'tests',
        'vendor',
        'storage',
        'public/storage',
        'bootstrap/cache',
        '.env*',
        '.phpunit.result.cache',
        '.styleci.yml',
        '.DS_Store',
        'herd.yml',
        'jsconfig.json',
        'phpunit.xml',
        'README.md',
    ],
    'flags' => 'rz',
    'options' => ['delete'],
    'timeout' => 60,
]);

// ---- ホスト定義(本番)----
host('prod')
    ->set('hostname', '*****.xserver.jp')
    ->set('remote_user', 'productionuser')
    ->set('identity_file', '~/.ssh/production_xserver')
    ->set('deploy_path', '/home/productionuser/production.example.com/script/sample-laravel')
    ->set('port', 10022)
    ->set('http_user', 'productionuser')
    ->set('cache_clear_url', 'https://production.example.com/clear.php');

// ---- ホスト定義(ステージング)----
host('stg')
    ->set('hostname', '*****.xserver.jp')
    ->set('remote_user', 'staginguser')
    ->set('identity_file', '~/.ssh/staging_xserver')
    ->set('deploy_path', '/home/staginguser/staging.example.com/script/sample-laravel')
    ->set('port', 10022)
    ->set('http_user', 'staginguser')
    ->set('cache_clear_url', 'https://staging.example.com/clear.php');

// ---- カスタムタスク ----
task('npm:build', function () {
    runLocally('npm run build');
});
task('local:sync', ['npm:build', 'rsync']);

task('cache:clear', function () {
    fetch('{{cache_clear_url}}');
});

task('artisan:queue:restart', function () {
    run('{{bin/php}} {{release_or_current_path}}/artisan queue:restart');
});

// ---- フック ----
task('deploy:update_code')->disable();
after('deploy:release', 'local:sync');
after('deploy:vendors', 'artisan:queue:restart');
after('deploy:cleanup', 'cache:clear');
after('deploy:failed', 'deploy:unlock');

基本設定

add('shared_files', ['public/.htaccess']);
set('keep_releases', 3);
set('bin/php', '/usr/bin/php8.2');
set('bin/composer', '/usr/bin/php8.2 ~/bin/composer.phar');
  • keep_releases:サーバー上に残す過去リリース数。3 なら直近3世代を保持し、rollbackで戻せます。
  • bin/php:XserverはPHPがバージョン別のパスになっているため、/usr/bin/php8.2 のように明示します。
  • bin/composer:Composerはグローバル導入されていないので、composer.phar をPHPで実行するパスを指定します。

rsync 設定

rsync_src に転送元(ローカルのプロジェクトルート)、rsync_dest に転送先(今回のリリースディレクトリ)を指定します。exclude には .envnode_modulesvendorstoragebootstrap/cache など、サーバー側で管理・生成すべきものを列挙し、rsyncで上書きしないようにします。optionsdelete は、転送元に存在しないファイルを転送先からも削除するオプションです。

shared / writable の設定(.env・storage・bootstrap/cache)

リリースごとにディレクトリが切り替わるDeployerでは、「リリース間で共有したいファイル」と「書き込み権限が必要なディレクトリ」を分けて扱います。recipe/laravel.php は次の内容をあらかじめ登録しています。

設定既定値(Laravel recipe)役割
shared_files.envリリース間で共有するファイル。{{deploy_path}}/shared/ に実体を置き、各リリースからシンボリックリンク
shared_dirsstorageリリース間で共有するディレクトリ。ログ・アップロード・キャッシュが世代をまたいで引き継がれる
writable_dirsbootstrap/cache, storageWebサーバーが書き込むディレクトリ。deploy:writable で権限が付与される

それぞれの配置と権限のポイントは以下です。

  • .envshared_files なので実体は {{deploy_path}}/shared/.env初回デプロイの前に、このパスへ本番用の .env を自分で配置します(SCPやサーバー上の vi で作成)。権限は chmod 600 が無難です。rsyncの exclude.env* を入れているのは、この共有ファイルを転送で上書きしないためです。
  • storageshared_dirs なので実体は {{deploy_path}}/shared/storage。デプロイのたびに作り直されず、ログやアップロードファイルが保持されます。excludestorage を入れているのも同じ理由です。
  • bootstrap/cachewritable_dirsconfig:cache などが書き込むため、書き込み権限が必要です。rsyncでは exclude し、サーバー側で deploy:writable により権限を確保します。

Xserverは sudo が使えないため、writable_use_sudofalsewritable_modechmod にしておくと権限付与でつまずきません。

ホスト定義(Xserver)

本番(prod)とステージング(stg)をホストとして分けて定義します(完成例の該当部分を再掲)。

本番(prod)

host('prod')
    ->set('hostname', '*****.xserver.jp')
    ->set('remote_user', 'productionuser')
    ->set('identity_file', '~/.ssh/production_xserver')
    ->set('deploy_path', '/home/productionuser/production.example.com/script/sample-laravel')
    ->set('port', 10022)
    ->set('http_user', 'productionuser')
    ->set('cache_clear_url', 'https://production.example.com/clear.php');

ステージング(stg)

host('stg')
    ->set('hostname', '*****.xserver.jp')
    ->set('remote_user', 'staginguser')
    ->set('identity_file', '~/.ssh/staging_xserver')
    ->set('deploy_path', '/home/staginguser/staging.example.com/script/sample-laravel')
    ->set('port', 10022)
    ->set('http_user', 'staginguser')
    ->set('cache_clear_url', 'https://staging.example.com/clear.php');

ホスト定義を分けることで、コマンド引数を指定するだけで本番/ステージングを切り分けられます。port がXserverのSSHポート 10022 である点に注意してください。

# ステージング環境へのデプロイ
./vendor/bin/dep deploy stg

# 本番環境へのデプロイ
./vendor/bin/dep deploy prod

他にも Selector の機能を使う事でラベルを指定、複数のアプリケーションサーバーやバッチサーバーなども切り分けられるので必要に応じて設定してみてください。

カスタムタスク

npm ビルドとrsync実行

task('npm:build', function () {
    runLocally('npm run build');
});
task('local:sync', [
    'npm:build',
    'rsync',
]);

デプロイを実行しているローカル環境で必要な処理として npm run build があります。開発時のjsビルドではなく、本番環境向けのビルドを実行してからrsyncを行う local:sync タスクを定義します。runLocally() はローカルで、run() はサーバー上で実行される点が違いです。

Composer・migration・キャッシュ生成(recipe組み込み)

Composerインストール・migration・各種キャッシュ生成は、recipe/laravel.phpdeploy タスクに最初から組み込まれています。あとで示すタスクツリーのとおり、次の順で自動実行されます。

  • deploy:vendorscomposer install --no-dev --optimize-autoloader 相当を実行
  • artisan:storage:linkphp artisan storage:link
  • artisan:config:cache / route:cache / view:cache / event:cache:本番用の各種キャッシュを生成
  • artisan:migrate:本番では --force 付きでマイグレーションを実行

Composerのメモリ不足でこける場合は set('composer_options', '...') の調整や、bin/composer の指定を見直してください。

queue(キュー)ワーカーの再起動

キューワーカーを常駐させている場合、デプロイ後は古いコードを掴んだままのワーカーを入れ替える必要があります。queue:restart を叩くタスクを追加し、deploy:vendors の後にフックします。

task('artisan:queue:restart', function () {
    run('{{bin/php}} {{release_or_current_path}}/artisan queue:restart');
});
after('deploy:vendors', 'artisan:queue:restart');

Xserverでのキューワーカーの常駐・cron設定については、別記事の Laravelのjob/queueをレンタルサーバーで実行するためのコツ もあわせて参考にしてください。

キャッシュクリア用タスク

XserverにはOPcacheが導入されており、これはDeployerのようなシンボリックリンクを貼り替えるデプロイ方式とは相性が悪いのでキャッシュ削除をする必要があります。以下参考情報

そのため、キャッシュ削除する処理を作成し、Apache経由でキャッシュ削除するURLにアクセスすることでキャッシュクリアを行います。

task('cache:clear', function () {
    fetch('{{cache_clear_url}}');
});

cache_clear_url にキャッシュクリア用のURLを設定しておきます(ホスト定義内の cache_clear_url)。clear.php は以下の設定で public/ 配下に作成しておきます。

// public/clear.php
<?php

opcache_reset();

OPcacheの削除方法そのものについては エックスサーバーの強力なキャッシュ、OPcacheを削除する で詳しく解説しています。

デプロイフックの設定

task('deploy:update_code')->disable();

after('deploy:release', 'local:sync');
after('deploy:vendors', 'artisan:queue:restart');
after('deploy:cleanup', 'cache:clear');
after('deploy:failed', 'deploy:unlock');

deploy:update_code は本来 git からソースを取得する処理なので、disable() で無効化し、代わりに deploy:release の後に local:sync(npmビルド+rsync)が実行されるようフック登録します。deploy:failed にフックした deploy:unlock は、失敗時にロックを解除して次のデプロイを妨げないための保険です。

デプロイ手順

  1. .env をサーバーの {{deploy_path}}/shared/.env に用意しておきます(もしくは最初の数回は失敗させながら、実ファイルが作成されたら本番用に設定するなど)。
  2. ./vendor/bin/dep deploy stg でステージングへデプロイを実行します。
  3. デプロイされたら、Xserverの公開ディレクトリ(例:~/staging.example.com/public_html)から {{deploy_path}}/current/public へシンボリックリンクを設定します。
  4. ステージングで問題なければ ./vendor/bin/dep deploy prod で本番へ反映します。

コマンドを実行すると以下のタスクツリーの流れで処理が進みます。deploy:update_codedisabled になり、代わりに local:sync(npm:build → rsync)が走っている点、末尾で cache:clear が実行されている点を確認してください。

% ./vendor/bin/dep tree deploy
The task-tree for deploy:
└── deploy
    ├── deploy:prepare
    │   ├── deploy:info
    │   ├── deploy:setup
    │   ├── deploy:lock
    │   ├── deploy:release
    │   ├── local:sync  // after deploy:release
    │   │   ├── npm:build
    │   │   └── rsync
    │   ├── deploy:update_code  // disabled
    │   ├── deploy:env
    │   ├── deploy:shared
    │   └── deploy:writable
    ├── deploy:vendors
    ├── artisan:storage:link
    ├── artisan:config:cache
    ├── artisan:route:cache
    ├── artisan:view:cache
    ├── artisan:event:cache
    ├── artisan:migrate
    └── deploy:publish
        ├── deploy:symlink
        ├── deploy:unlock
        ├── deploy:cleanup
        ├── cache:clear  // after deploy:cleanup
        └── deploy:success

current切り替えとrollback(切り戻し)

Deployerはリリースごとに releases/1, releases/2… とディレクトリを作り、デプロイ成功時に deploy:symlinkcurrent シンボリックリンクを最新リリースへアトミックに張り替えます。Xserverの公開ディレクトリを current/public に向けておけば、切り替えの瞬間だけ参照先が変わり、ダウンタイムなく公開できます。

デプロイ後に不具合が見つかった場合は、rollback で直前のリリースへ即座に戻せます。

# 直前のリリースへ切り戻し
./vendor/bin/dep rollback prod

# 保持されているリリース一覧を確認
./vendor/bin/dep releases prod

keep_releases で指定した世代数だけリリースが残るため、その範囲で戻せます。注意点として、rollbackでは cache:clear が自動実行されません。OPcacheが古いコードをキャッシュしたままになることがあるので、切り戻し後は clear.php のURLへアクセスしてOPcacheをリセットしてください。

Xserverでハマりやすいポイント

Xserver特有でつまずきやすいのは、SSH・PHPパス・権限・コマンド実行まわりです。よくある問題と対処をまとめました。

項目起きやすい問題対処
SSH接続ポート22で繋がらない/認証に失敗するポートは 10022。サーバーパネルでSSHを有効化し公開鍵を登録。identity_file で鍵を明示
PHPパスphp artisan が古いPHPで動くwhich php はCLI既定版。bin/php/usr/bin/php8.2 のようにバージョン付きパスを指定
Composercomposer コマンドが無いcomposer.phar~/bin に置き、bin/composerphp8.2 ~/bin/composer.phar に設定
権限deploy:writable でsudoエラーwritable_use_sudofalsewritable_modechmod
公開ディレクトリドキュメントルートが public_html 固定public_html から current/public へシンボリックリンク。サブディレクトリ公開は別記事参照
OPcacheデプロイしても古い挙動のままclear.phpopcache_reset())へアクセスしてリセット
Node.jsサーバー上でnpmビルドが動かないビルドはローカルで実行しrsyncで転送(本記事の方式)。GLIBC問題は別記事参照

公開ディレクトリの切り替え(サブディレクトリ配下での公開)については Laravel8系でサブディレクトリ配下の公開に対応する が参考になります。

デプロイ後にキャッシュ由来の不具合が残る場合は Laravel キャッシュクリアができない場合のトラブル改善方法、稼働中のLaravelバージョンを確かめたいときは Laravelのバージョン確認方法|artisan・Composer・ファイルで確認 を確認してください。

まとめ

Deployer + rsync によるLaravelアプリの公開は、ビルドをローカルで完結できるため、サーバーにNode.jsやnpmを導入する必要がなく、セキュリティや負荷の観点でも非常にスマートです。deploy.php の完成例・sharedwritable 設定・.env/storageの配置・migrationやqueue再起動・rollbackまで押さえておけば、初回デプロイから日々の運用までひととおり回せます。

Xserverのように、GLIBCのバージョンが低いために必要なNode.jsのバージョンを導入する手間がある環境でもこの方法なら対応可能です。これからLaravelを本番公開する方は、ぜひこの方法を参考にしてみてください!

ホーム » 記事一覧 » .htaccess » DeployerでLaravelをrsyncデプロイ – Xserverへの効率的な公開設定

投稿者

ここまで読んでいただき、ありがとうございます。

このサイトでは、私自身が関わっていることや、興味を持って試していることをそのまま置いています。

内容を見ていて、
「少し話を聞いてみたい」
「協業できる部分がありそう」
と感じる点があれば、下記のお問い合わせフォームからご連絡ください。状況を確認したうえで、必要な範囲でお返事します。

特に、以下のWordPressサイトに関する相談にも対応しているのでご興味ありましたらご相談ください。


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です