PhpStorm の Run/Debug で docker-compose run でテストを実行

docker-compose で複数のコンテナで構成されている環境に対して、PhpStorm の Run/Debug で docker-compose run でテストなどを実行できるようにしたときのメモ。


PhpStorm 2016.1 ぐらいから Remote interpreter に Docker が追加されており、PhpStorm の Run/Debug で「コンテナ作成&スクリプトやテスト実行」ができるようになっています。

Xdebug を実行する PHP のイメージにインストールしておけばデバッガでアタッチすることもでき、非常に便利そうですが・・・

単一のイメージから単一のコンテナを作成して実行するだけなので、docker-compose などで複数のコンテナ(DBとか)を実行する構成だと Run/Debug でテストを実行したときに DB が無くてテストがコケます。

docker run ではなく docker-compose run できれば解決なのだけれども。。。

いずれ出来るようになりそうな気がするけど、当座の方法として Vagrant の Remote interpreter で php executable を docker-compose run で php のコンテナを実行するシェルスクリプトに差し替えることで対応しました。

方法

下記のように設定します。

  • Vagrant 環境に docker-engine と docker-compose をインストール
    • docker は vagrant ユーザーから実行できるようにする
  • docker-compose.yml で下記をマウントするように設定
    • $PWD:$PWD:rw
      • /vagrant:/vagrant:rw とかでも ./:/vagrant:rw とかでも良い
    • $HOME:$HOME:ro
      • /home/vagrant:/home/vagrant:ro とかでも良い
  • Remote interpreter の php executable で後述のスクリプトを指定する

Vagrantfile で synced_folderssh.username を変更したときのことを考慮して $PWD とか $HOME とか使っているけどベタに書いても構いません。

php executable に指定するスクリプトは下記の内容で、プロジェクトルートに配置します。

#!/bin/bash

cd -- "$(dirname -- "$(readlink -f -- "$0")")" # `cd /vagrant` とかでも良い

exec docker-compose run --rm -T -w "$OLDPWD" \
  -e SSH_CLIENT="$SSH_CLIENT" -e XDEBUG_CONFIG="$XDEBUG_CONFIG" php php "$@"

2つある php の1つめは docker-compose はサービスの名前なので、適宜変更のこと。

後は Vagrant 環境の中で docker-compose up でコンテナを開始し、PhpStorm の Run/Debug でテストなどを実行すると docker-compose run で実行されます。

php のイメージに xdegug をインストールしておけばブレークポイントを仕込んで止めたり出来ます。

試行錯誤のメモ

プロジェクトルートのディレクトリ

コンテナ内でのプロジェクトルートのディレクトリは Vagrant 環境でのディレクトリと同じディレクトリになる必要があります。 そうしないと、リモートデバッグ時にコンテナ内の xdebug から通知されるパスと、ローカルの実際のパスの対応がとれません。

普通は /vagrant:/vagrant:rw とかだけど、Vagrantfile で、

config.vm.synced_folder ".", "/app"

のように変更しているなら /app:/app:rw とかに変更します。

このディレクトリは docker-compose 実行時のカレントディレクトリになるはずなので $PWD:$PWD:rw とかでも良いです。↑ではそうしてます。

Vagrant ユーザーのホームディレクトリ

PhpStorm の Vagrant の Remote inspector は Vagrant のログインユーザーのホームディレクトリに .phpstorm_helpers/phpinfo.php というファイルを配置し、これを実行することで環境の情報を得ます。

ので、このファイルがホスト(Vagrant 環境)とコンテナで共有されている必要があります。

↑ではホームディレクトリまるごとを共有しています。

SSH_CLIENT 環境変数

xdebug.remote_host の値の算出のために SSH_CLIENT 環境変数 が使用されるので、ホストの SSH_CLIENT 環境変数をコンテナにそのまま渡す必要があります。

XDEBUG_CONFIG 環境変数

リモートデバッグの開始のために XDEBUG_CONFIG 環境変数が必要なので、ホストの XDEBUG_CONFIG 環境変数をコンテナにそのまま渡す必要があります。

Local interpreter ではダメ?

Vagrant を噛まさずに Local の interpreter で php executable を↑のようなスクリプトにすれば、Docker for Mac で同じことが実現できるかと思ったけれども、xdebug.remote_host が 127.0.0.1 固定になるようで、コンテナから 127.0.0.1 ではホストにアクセスできないのでダメでした。

また、そもそも Docker for Windows だとパスの対応が取れなくてダメだと思います(C:\Users\ore -> /C/Users/ore とか)。

今回は Mac で試しているのだけど Windows でも出来るようにしたいので Vagrant のが無難だろうと思います。

スクリーンショット

f:id:ngyuki:20170326102634p:plain

f:id:ngyuki:20170326102646p:plain

f:id:ngyuki:20170326102652p:plain