17
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vagrant(+Docker) 上のPHPアプリをデバッグ実行する

Last updated at Posted at 2018-08-23

:worried: デバッガが反応しないんだけど..

仮想環境で開発をしていると、間に挟まるレイヤーのせいで悩まされることが度々あります。
例えば、ホスト側でIDEを実行し、ゲスト側で開発対象のアプリを起動しているような場合、デバッグ実行をするためには適切な設定が必要になります。
ゲストOSからは、デバッガがリモートホストで実行されているように見えるからです。
ここでは、ゲストOSでPHPを実行して、ホストOS上のデバッガでデバッグする方法を紹介します。

想定環境

Vagrant でゲストOSを起動し、ゲストOS上のDockerコンテナでPHPアプリを実行します (Dockerを使わず、ゲストOS上で直接PHPを実行する場合でも、下記の方法でデバッグ実行できるようになるはずです)。

Vagrant のプロバイダには、VirtualBox を使います。
VirtualBox 限定の設定を使うので、他のプロバイダでは他の方法が必要なります。ごめんなさい。

バージョン
macOS 10.13.6
Vagrant 2.1.2
VirtualBox 5.2.16
PHP 7.2.9
Xdebug 2.6.1

デバッガとしては、PHP Debug 拡張をインストールした Visual Studio Code (以下 VS Code) を使いました。

バージョン
VS Code 1.26.1
PHP Debug 1.12.4

Xdebugによるデバッグの仕組み

PHPアプリのデバッグ実行には、Xdebug というPHP拡張を利用します。
Xdebug

PHP ランタイムに組み込まれたXdebugとデバッガが通信することにより、リモートデバッグが実行されます。
PHPアプリとデバッガを両方ともホストOSで起動していれば、特別な設定をしなくても通信が成立して問題なくデバッグできます。
img1.png

PHPアプリをゲストOSで実行する場合、通信先のデバッガが localhost にないので、通信に失敗します。
img2.png

解決策

要するに、XdebugがホストOSのデバッガと通信できるよう、Xdebugを設定すればいいわけです。
方法は2つあります。

:neutral_face: 方法1: xdebug.remote_connect_back を有効にする

Xdebug の設定ファイル (xdebug.ini) で、xdebug.remote_connect_back を有効にします。

xdebug.default_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1 # <- ここ
xdebug.remote_enable = 1
xdebug.remote_port = 9000

これは、PHPにHTTPリクエストが届いたときに接続元のホストを取得して、Xdebugからそのホストに対して通信を行う設定です。
$_SERVER['HTTP_X_FORWARDED_FOR']$_SERVER['REMOTE_ADDR']から接続元のホストを判定します。
PHPが受け取るHTTPリクエストの通信元は、VirtualBoxのNATアダプタによって変換されていますが、このIPアドレスに対して通信を行うことで、デバッグセッションが成立します。
img3.png

ブラウザからのリクエストをトリガーにしてデバッグする場合はこの設定でOKです。
ただし、CLIなど別の方法で起動したPHPに対しては、この方法ではデバッグを実行することができません。例えば、PHPUnitでユニットテストをするケースなどが該当します。

ブラウザからのリクエストとコマンド実行の両方で、デバッグ実行をしたい場合は、この方法は適しません。
次に説明する方法2の設定を選んで下さい。

:grinning: 方法2: xdebug.remote_host に、10.0.2.2 を指定する

Xdebug の設定ファイル (xdebug.ini) の xdebug.remote_host で、通信先のホストを明示的に指定します。

xdebug.default_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 0 # 無効にする
xdebug.remote_enable = 1
xdebug.remote_host = "10.0.2.2" # <- ここ
xdebug.remote_port = 9000

10.0.2.2 はVirtualBox の NAT アダプターのゲートウェイアドレスです。
Fine-tuning the VirtualBox NAT engine

img4.png

この設定により、Xdebugは常にホスト上のデバッガと通信するようになります (ブラウザからのリクエストとコマンド実行の両方)。
VagrantでDockerを起動して、コンテナ内で PHP を実行する場合でも、この方法でデバッガと通信できます。

デバッガの設定

xdebug.iniの設定で、Xdebugとデバッガは通信できるようになりました。
さらに、仮想環境とホスト側とファイルのパスをマッピングすることで、VS Codeで設定したブレークポイントが有効になります。
例えば、PHPサーバー側(ゲストOS)の /var/wwwを、VS Codeのワークスペースのwwwディレクトリにマッピングするには、.vscode/launch.json を次のように設定します。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log": true,
            "pathMappings": {
                "/var/www": "${workspaceRoot}/www"
            }
        },
        ...
    ]
}

補足

Xdebugとデバッガとの通信は、Xdebug(ゲストOS)からデバッガ (ホストOS) に対して送信されるので、ポートフォワーディングなどの設定は必要ありません。

17
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?