Dockerで構築したPHP環境をxdebugでデバッグ（vscode）

# はじめに

dockerで構築したPHP環境でステップ実行する際の手順です。
エディターはvscodeでの手順になります。
使用しているdockerはdocker for macのversion 18.06です。

## 今回説明しないもの

- Dockerの基本的な使い方
- vscodeの基本的な使い方

# ディレクトリ構造
今回の設定のディレクトリ構造です。

```
├── docker
│   ├── Dockerfile
│   └── php.ini
├── docker-compose.yml
└── src
    └── index.php
```

# Dockerfileの設定

Dockerfileを書いていきます。

```Dockerfile
FROM php:7.2-apache

RUN pecl install xdebug \
  && docker-php-ext-enable xdebug

WORKDIR /var/www
```

DockerhubからPHP公式が配布しているwith apacheのものを使用しています。
そこにxdebugをインストールします。
また`docker-php-ext-enable`でpecl拡張を有効化できるので`docker-php-ext-enable xdebug`を実行します。
上記を実行することで`/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini`に

```ini
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/xdebug.so
```
が出力されます。(内容は個人によって異なる可能性があります)

# docker-compose.ymlの設定

compose fileのversionが3.7なのでそれに合わせて記述しています。

```yml
version: "3.7"
services:
  php:
    build:
      context: ./docker
    ports:
      - "8081:80"
    tty: true
    stdin_open: true
    volumes:
      - ./src:/var/www/html
      - ./docker/php.ini:/usr/local/etc/php/php.ini
```

volumesで追加しているphp.iniですが、デフォルトではdockerにはphp.iniはないので、ローカルにphp.iniを作ってdocker側に追加させています。
今回の場合はローカルに書いたphp.iniはDockerfileと同じ場所に配置していますが、変更する場合はパスを変更してください。

php.iniの内容は以下のようになっております。

```ini
[xdebug]
xdebug.remote_enable=1
xdebug.remote_autostart=1
; ホスト側のIP
; host.docker.internalはdockerのhostマシンのIPを解決してくれます。
; hostマシン以外のIPの場合は適宜IPを調べて設定してください。
xdebug.remote_host=host.docker.internal
; 空いているport番号（xdebugのデフォルトは9000）。私の場合は他と競合していたので9001に設定。
xdebug.remote_port=9001
; xdebugの出力するログの場所。今回は適当に/tmp配下に。
xdebug.remote_log=/tmp/xdebug.log
```

# vscodeの設定

docker側の設定はほぼ終わったので、vscodeの方の設定を行います。
まずはPHPDebugの拡張機能をインストールしましょう。
インストールできましたらlaunch.jsonの設定を行います。
vscodeの画面の左側にある虫のようなマークをクリックしてください。
すると下の画像のような表示になるかと思います。
<img width="370" alt="スクリーンショット 2018-09-01 19.26.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/233792/2b2e9d40-5562-49ee-db47-6798c4e48f20.png">
歯車のマークを押すと環境を聞かれますのでPHPを選択してください。
選択しますと、launch.jsonが自動的に作成され編集画面になります。
表示されましたら、launch.jsonの`configrations`に下記を追記してください。

```json
    "configurations": [
        {
            "name": "XDebug on docker",
            "type": "php",
            "request": "launch",
            "port": 9001,//php.iniで設定したxdebug用のport番号
            "pathMappings": {
                // {docker上のdocument root}:{ローカルのdocument root}
                "/var/www/html":"/Path/to/your/local/root"
            }
        }
    ]
```
これで一旦vscodeの設定はおしまいです。

# デバッグ開始
では最後に実際にステップ実行を行います。
まずは`docker-compose up -d`でコンテナを起動してください。
できましたら、vscodeの方でソースコードにブレークポイントをつけてみましょう。
<img width="1072" alt="スクリーンショット 2018-09-01 21.54.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/233792/c40c802c-1a04-40ff-46be-d73bd9ca2cda.png">
上の画像のようにソースの行番号の左をクリックするとブレークポイントを設定できます。
また、画面の左にある緑色の矢印もクリックしておきましょう。
クリックしますと、ブレークポイントまでphpが実行された際にそこでストップするようになります。
やめる場合は画面の中央にあるツールバーの停止ボタンを押してください。
この状態でlocalhost:8081にアクセスするとブレークポイントで実行が停止し、ステップ実行が可能になります。
また、左の方に現在変数に入っている値なども見ることができたりしますので、各々ご活用ください。

以上、Dockerで構築したPHP環境をxdebugでデバッグする方法でした。

# 参考

- https://docs.docker.com/docker-for-mac/networking/
- https://hub.docker.com/_/php

# 編集履歴
- 2019/05/10 コメントでいただいた指摘に基づき`docker-php-ext-enable xdebug`および`docker.host.internal`の記述を追加

# 追記（2021/1/31）
xdebug3系がリリースされ、`pecl install xdebug`を実行すると3系がインストールされるようになりました。
この記事に記載されているxdebugの設定は2系のものなのでそのままコピーしてもブレイクポイントで止まらないなどの問題が発生するかと思います。
その場合はxdebug3系の設定に書き換えてください。
詳しくはislandryuさんが下記記事で説明してくださっています。ありがとうございます。
https://qiita.com/islandryu/items/b5fbebb41f6d60fcf0c2