Macにxdebugをインストールせずに、VSCode+Remote ContainerでPHP+Laravelのデバッグ環境を構築する

# はじめに

PHPのデバッグを行うには、[xdebug](https://xdebug.org/)が必要です。
しかし、Mac OSのバージョン(Catalina/Mojave)によっては、これをインストールするのが困難です。

Macにxdebugをインストールせずに、PHPのデバッグを実現するために、VSCode+Remote Containerによって環境を構築を行いました。
その手順について説明しています。

# 発生した問題

xdebugインストールを行おうとして・・・下記のように、エラーとなってしまい途方にくれました。

```shell:install-xdebug
$ pecl install xdebug
WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update
downloading xdebug-2.9.2.tgz ...
Starting to download xdebug-2.9.2.tgz (242,959 bytes)
..................................................done: 242,959 bytes
90 source files, building
running: phpize
grep: /usr/include/php/main/php.h: No such file or directory
grep: /usr/include/php/Zend/zend_modules.h: No such file or directory
grep: /usr/include/php/Zend/zend_extensions.h: No such file or directory
Configuring for:
PHP Api Version:
Zend Module Api No:
Zend Extension Api No:
autom4te: need GNU m4 1.4 or later: /usr/bin/m4
ERROR: `phpize' failed
$
```
ここら辺の問題は、

https://bbqsoftwares.com/blog/xdebug-catalina-issue

などで詳しく説明されていますが、根本的には `/usr/include` への書き込みができなくなった事が起因しています。
頑張れば、インストールできるみたいですが、頑張りたくないです。

# 環境構築

## 前提条件

下記環境で試しています。

- OS : MacOS Catalina ( 10.15.3)
- Docker for Mac : 2.2.2.0 (Docker version 19.03.5, build 633a0ea) 
- VSCode : 1.43.0

## VSCodeのアドオンを追加

[Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)をインストール。インストールボタンを押すだけ。

## Remote - Containersの準備

ベースとしては、
https://github.com/laravel/quickstart-basic.git
を利用します。
ここに書いた結果は、全て
https://github.com/h-r-k-matsumoto/quickstart-basic.git
にあります。
差分は、
https://github.com/laravel/quickstart-basic/compare/laravel:master...h-r-k-matsumoto:master
です。

### dockerコンテナの定義

Dockerfileを用意します。
PHPのバージョンはお好きなものを使ってください。
`docker-php-ext-enable` にてxdebugを有効化します。これは、dockerhubのPHPの[説明](https://hub.docker.com/_/php)にその方法が記載されています。
あとは、laravelで必要な拡張モジュールをインストールします。

```dockerfile
FROM php:7.2

RUN apt-get update \
  && apt-get -y install git zip unzip

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

RUN curl -O https://getcomposer.org/download/1.10.0/composer.phar \
  && chmod u+x composer.phar \
  && mv composer.phar /usr/local/bin/composer

WORKDIR /workspace

CMD [ "php", "artisan", "serve" , "--host=0.0.0.0" ]
```

docker-compose.ymlを用意します。
`web`は、デバッグ対象となるlaravelアプリケーションのコンテナです。
ソースファイルを、 `/workspace` にマウントします。**これは、Remote Containersで実行する場合は、利用されません。**
マウント箇所は後述しますが、`docker-compose up -d` にて動かせるようにマウントポイントを記述しておいた方が便利です。
また、`db`は、laravelからアクセスするmysqlのコンテナです。

```yaml:docker-compose.yml
version: '3.1'
services:
  web:
    hostname: web
    container_name: web
    build: .
    volumes: 
      - ./:/workspace
      - ./docker/php:/usr/local/etc/php/
    ports:
      - 8000:8000

  db:
    hostname: db
    container_name: db
    image: mysql:5.7
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: pass
      MYSQL_DATABASE: homestead
      MYSQL_USER: homestead
      MYSQL_PASSWORD: secret
    volumes:
      - db-data:/var/lib/mysql
    ports:
      - 3306:3306

volumes:
  db-data:
```

### Remote-Containersの準備

メニューの`[View]` -> `[Command Pallete]`を実行します。
そして、`Remote-Containers: Add Development Container Configuration Files...` を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/e59a6dd2-a3ac-f476-7998-017c192e40d3.png)


次に、 `From 'docker-compose.yml'`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/b2c5483d-b6aa-a143-6d63-263ac0266789.png)


そして、デバッグ対象となるコンテナの `web` を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/d2354ef1-8434-2950-d61b-8851de4b807c.png)

すると、 `.devcontainer` ディレクトリに、下記2つのファイルが作成されます。

 - devcontainer.json
 - docker-compose.yml

`devcontainer.json` には、開発環境となるコンテナの設定情報が記載されています。変更する箇所は、`extensions`の箇所となります。下記のように、3つのextensionを追加します。IDは、アドオンの追加するサイトのURLで確認できます。

例：https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-intellisense

上記であれば、 `felixfbecker.php-intellisense` になります。

```json:devcontainer.json
	"extensions": [
		"felixfbecker.php-debug",
		"felixfbecker.php-intellisense",
		"bmewburn.vscode-intelephense-client"
	]
```

`docker-compose.yml` では、元々用意されていた `docker-compose.yml` ファイルの上書きする設定が記載されています。
`workspace`へのマウント、及びcommandとして`/bin/sh -c "while sleep 1000; do :; done"`が記載されています。

### Remote-Containersの起動

`Remote-Containers: Open Folder in Container`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/b11da2fc-1f87-0598-33f6-fffebd2554e3.png)

そして、設定したプロジェクトのディレクトリをそのままOpenします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/e8946e87-864c-391e-0399-6ea2990a6887.png)

下記のように、タイトルの部分にて、`Dev Containers: Existing Docker Compose...`と表示されれば成功です！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/59cb6e73-2107-0ea4-185d-bd8e936be88a.png)
　

### Laravel実行準備

ここからは通常の開発と同様になります。composerのinstallを行います。VSCodeのTERMINALで実行します。

```shell:composer-install
root@web:/workspace# composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 43 installs, 0 updates, 0 removals
  - Installing symfony/event-dispatcher (v3.0.2): Downloading (100%)         
  - Installing psr/log (1.0.0): Downloading (100%)      
・・・省略・・・
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
Generating autoload files
> php artisan clear-compiled
> php artisan optimize
Generating optimized class loader
root@web:/workspace# 
```

migrateにてスキーマを構築します。

```shell:migrate
root@web:/workspace# php artisan migrate             
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_10_27_141258_create_tasks_table
root@web:/workspace# 
```

最後に、`php artisan serve --host=0.0.0.0`を実行してみましょう。ホストマシン側からアクセスしないのであれば、`--host`は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/0fe67c8b-aff5-9c88-e91b-fd6fe9a3e07c.png)

http://localhost:8000/ にアクセスして、画面が表示されれば成功です！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/e57e3518-9d36-88ef-172a-b343efce483f.png)

# デバッグをする

`create a launh.json file]` をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/7d29137d-8856-b60d-c5ba-5c6601881c81.png)

`PHP`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/b61ea781-a03b-01ce-a873-757bd20299b8.png)

`launch.json`ファイルが出来上がります。そして、そのまま`Listen for XDebug`を選択してデバッグを開始します。

適当にブレイクポイントを作成します。今回は、`/app/routes.php`に作成しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/2d966236-8df2-04ec-304f-3f479457520b.png)

そして、laravelを`php artisan serve --host=0.0.0.0`コマンドで起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/5fbd9d13-0338-cc0c-a5af-20c4be394000.png)

そして、`http://localhost:8000/`にアクセスします。
はい！無事デバッグができるようになりました！！！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/83b8f605-4d56-a747-b312-f2c3e69b970b.png)

# 所感

- 最初に作る時は、ちょっと覚える事が色々あって大変かもしれない。
- いったん作ってしまえば、環境構築がとても、楽。全部docker-compose/dockerで管理できる。環境依存度が減る。


# 留意事項

- redisの接続部分までは作っていません。気が向いたら作ります。
- 動作確認はあまりしていないので、拡張モジュールが色々と足りない可能性があります。

# 参考

- https://hub.docker.com/_/php
  - xdebugの有効化はこちらを参照してください。
  - docker-php-ext-installに関してはこちらを参照してください。
- https://bbqsoftwares.com/blog/xdebug-catalina-issue
  - xdebugがインストールできない問題は、こちらが詳しいと思います。