例えば AWS の EC2 インスタンスに Docker Engine を入れて、その Docker を用いて PhpStorm+Xdebug で開発するメモ。
なお、PC 側は Windows 10 で WSL です。
Docker Remote API
EC2 インスタンス上の Docker で Remote API を有効にします。以下のいずれでもお好みで良いと思います。
- TLS 有効で 0.0.0.0
-H 0.0.0.0:2376 --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/cert.pem --tlskey=/etc/docker/key.pem
- 証明書の管理がめんどくさくないなら
- TLS 無効で 0.0.0.0 でセキュリティグループでソースアドレスで制限する
-H 0.0.0.0:2375
- PC 側が固定IPで同じNATの内側に信頼できる端末しか無いなら
- TLS 無効で 127.0.0.1
-H 127.0.0.1:2375
- ssh でローカルポートを転送して Docker Remote API にアクセスする
今回は ssh でのポートフォワード前提になっているので、3番目の方法を用います。
sshd_config
ssh で -R
で xdebug のポートをリモート→ローカルに転送する必要があるのですが、素のままだとリモートでのリッスンポートがループバックデバイスのみリッスンするので、コンテナ内の xdebug から転送しているポートにアクセスできません。
リモートの sshd_config
で GatewayPorts yes
にすれば 0.0.0.0
でリッスンするので、コンテナ内からでも転送しているポートにアクセスできるようになります。
SSH でポートの転送
次のようにリモートサーバに ssh してポートを転送します。
ssh ore-no-server -D 1080 -R 9000:localhost:9000 -L 2375:localhost:2375 -N
-R 9000:localhost:9000
は Xdebug 用です。リモートサーバの 9000 ポートをローカルの 9000 ポートに転送します。
-L 2375:localhost:2375
は Docker Remote API 用です。ローカルの 2375 ポートをリモートの 2375 ポートに転送します。ローカルで Docker Desktop を実行しているなどで 2375 ポートが使えないなら -L 12375:localhost:2375
などと適当にポート番号は変えると良いです。
-D 1080
は Docker で Expose しているポートへブラウザからアクセスするための設定です。
.envrc
direnv の .envrc などで Docker のための環境変数を設定します。
export DOCKER_HOST=tcp://localhost:2375 export DOCKER_TLS_VERIFY=0
これでローカルの docker
や docker-compose
が SSH で転送されたポートを経由してリモートで実行されるようになります。
PhpStorm 設定
Build, Execution, Deployment > Docker
Docker サーバを追加します。TCP socket で tcp://localhost:2375
で OK です。
Path mappings はデフォルトの /c/Users -> C:\Users
が無難だと思います。
Languages & Frameworks > PHP
CLI Interpreter でインタプリタを Docker Compose で上で追加したサーバを指定して追加します。その他の設定はプロジェクトの構成にあわせて指定します。
さらに Addtional の Configuration options で xdebug.remote_host
でコンテナからみたリモートサーバの IP アドレスを指定します。コンテナに入って ip route show
で表示されるデフォルトゲートウェイを指定すれば OK です(Docker Desktop なら host.docker.internal
で良いですけど Linux だとそうもいかない)。
Languages & Frameworks > PHP > Test Framework
PHPUnit by Remote Interpreter で上で追加したインタプリタを選択して追加します。その他の設定はプロジェクトの構成にあわせて指定します。
ファイル同期
ローカルからリモートへファイルを同期させる必要があります。
バージョンを揃えたりがやや面倒ですが これ でも使用した unison が便利です。
docker run --rm -v /usr/local/bin:/x eugenmayer/unison:2.51.2.1 sh -c 'cp /usr/local/bin/unison* /x'
次のように同期を実行します。
unison . "ssh://ore-no-server/$PWD" -ignore 'Name .git' -ignore 'Name .idea' -auto -batch -repeat watch
ブラウザのプロキシ設定
ブラウザのプロキシ設定で SOCKS プロキシを localhost:1080
で設定します。
いちいち設定を切り替えるのは面倒だろので、簡単に切り替えられるアドオンを使うか、どこかに次のような proxy.pac を置いてブラウザに読ませると楽です。
function FindProxyForURL(url, host) { if (localHostOrDomainIs(host, "ore-no-server")) { return "SOCKS5 127.0.0.1:1080"; } return "DIRECT"; }
ブラウザで http://ore-no-server:9876
のように Docker で Expose しているポートにアクセスできるようになります(セキュリティグループでポートを開ける必要はありません)。
さいごに
特に変わったことはしていないけど sshd_config
に GatewayPorts yes
が必要というところにちょっと嵌ったのでメモ。
unison で vendor や node_modules まで同期されるのはやりすぎかもしれないので適宜設定は調整すると良いかもしれない。手元では↓みたいになってました。
unison . "ssh://root@ore-no-server/$(pwd -P)" \ -ignore 'Name .git' \ -ignore 'Name .idea' \ -ignore 'Name public' \ -ignore 'Name build' \ -ignore 'Name storage' \ -ignore 'Name vendor' \ -ignore 'Name node_modules' \ -auto -batch -repeat watch
ポートフォワードも -D 1080
ではなく Expose してるポートを個別に -L
で転送しても良いかと思います。手元では↓みたいになってました。これなら http://localhost:9876 でアクセスできるので Docker Desktop と使用感が近くなります。
ssh ore-no-server -N -D 1080 \ -R 9000:localhost:9000 \ -L 3000:localhost:3000 \ -L 9876:localhost:9876 \ -L 12376:localhost:2376 \ -L 3306:localhost:1330
修正したファイルが unison で同期されるまでに若干の待ちがあるのが欠点です。