Docker × Visual Studio CodeでPHP開発【デバッグ実行】

# はじめに

Visual Studio Code(以下、 VSCode)は軽量でとても便利ですよね。
Dockerも色々なインストールやセットアップの手間を省くことができるのでとても便利です。

今回はこれらを使用してPHPの開発環境を構築してみようと思います。

お忙しい方、すぐに使用したい方はこちらをCloneしてご利用ください。
https://github.com/MasanoriIwakura/php_study

また、本記事は[以前投稿した記事](https://qiita.com/MasanoriIwakura/items/92f11e31a58e559d7c28)のアップグレード版です。

# 前提

今回の開発環境は全てmacOS, Docker for Macを使用しています。
その他の環境では動作されていないため、動作確認は行なっておりません。

## [使用ツール]

|ツール名|バージョン|
|:--|:--|
|OS|macOS Mojava 10.14.3|
|Docker|Docker for Mac 18.06.1-ce|
|Docker Compose|1.22.0|
|PHP|7.2.7-apache (Apacheと連携されているコンテナ)|
|Xdebug|2.7.0|
|MySQL|8|
|phpMyAdmin|4.7|
|Visual Studio Code|1.31.1|

WindowsやLinux(GUI)環境の場合はDockerとVSCodeがあれば恐らく同じ構成が作成できると思います。

# Visual Studio Codeの準備

## インストール
インストールされていない方は以下からダウンロードしてインストールしてください。
https://code.visualstudio.com/

インストールが完了したら作業用のフォルダを作成し、VSCodeで開いてください。
※本記事では`php_study`フォルダ内で作業します。

## セットアップ

PHP用の拡張機能をインストールします。
左側の拡張機能アイコンをクリックまたは、[Shift + ⌘ + X]を押下し、検索ボックスで[PHP Debug]で検索
以下の拡張機能をインストールします。

こちらの拡張機能はVSCodeからPHPのデバッグ実行をするために必要です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/0b7329c4-89f6-c3d3-3093-ec1bc73cda86.png)

合わせてこちらもインストールしておきます。
こちらの拡張機能はVSCodeでPHPファイルを編集する際にインテリセンスが使えるようになります。
(インテリセンスはPHPの構文を入力する際に入力補完してくれます)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/e2d37b5c-e611-492e-eb63-e1b053188a95.png)

# Dockerの準備

折角なのでVSCodeのコンソールから実施します。
[Shift + cntrol + @]を押下し、VSCode上でコンソールを立ち上げます。
以下、こちらのコンソール上で作業します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/97335edc-9e7c-8dbb-eeef-9650ee9a81ea.png)


## Dockerのインストール

Dockerを導入していない場合、Macの場合は以下のコマンドで導入してください。
その他のOSの場合は自分で調べてみてください。

```bash
# Homebrewがインストールされていること
$ brew install docker
$ brew cask install docker
# インストール確認
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
```
`bash: docker: command not found`となった場合は手動でDockerを起動してください。
Macのアプリ一覧から以下のアイコンをクリックするだけでOK
(普通にインストールした場合はedgeの文字が入っていないかも)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/d97f0f63-b223-142b-19b8-eeaede54944e.png)


## Docker Composeのインストール

Macの場合は以下のコマンドだけでOK

```bash
$ brew install docker-compose
# インストール確認(私のバージョンは古いかも)
$ docker-compose --version
docker-compose version 1.22.0, build f46880f
```

## Dockerイメージの作成

公式のPHPイメージはデバック実行用のツールが入っていないため、自前でイメージを作成します。
VSCodeにて`php`フォルダを作成し、その中に`Dockerfile`を作成してください。

```bash
$ mkdir php
$ touch php/Dockerfile
```

Dockerfileの中身は以下。

```dockerfile:Dockerfile
FROM php:7.2.7-apache

RUN apt-get update && \
    docker-php-ext-install mysqli && \
    pecl install xdebug
```
### [解説]

`FROM php:7.2.7-apache`：
　PHPとApacheを連携したDocker公式イメージを使用します。

`RUN apt-get update等`：
　公式イメージはdebianを使用しているのでapt-getを使用してアップデートします。
　`mysqli`はPHPからMySQLを操作するライブラリです。
　`xdebug`はVSCodeからDocker上のPHPをデバッグ実行するのに使用します。

## docker-compose.ymlの作成

PHPコンテナ、MySQLコンテナを連携するために準備します。
MySQLは今回のデバッグとは直接関係ないですが、勉強用に入れます。

作業フォルダの直下に`docker-compose.yml`を作成します。

```bash
$ touch docker-compose.yml
```

```yml
version: '3'

services:
  php:
    build: ./php
    ports:
      - '80:80'
    volumes:
      - ./php/html:/var/www/html
      - ./php/conf/php.ini:/usr/local/etc/php/php.ini
      - ./php/log/xdebug:/var/log/xdebug
    links:
      - mysql

  mysql:
    image: mysql:8
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=app
      - MYSQL_USER=docker
      - MYSQL_PASSWORD=docker
    volumes:
      - ./mysql/conf:/etc/mysql/conf.d/
      - ./mysql/lib:/var/lib/mysql
      - ./mysql/sql:/docker-entrypoint-initdb.d

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:4.7
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=password
    ports:
      - 8080:80
    links:
      - mysql
    volumes:
      - ./phpmyadmin/sessions:/sessions
```

### [解説]

`php`：
　PHPコンテナの設定を行います。
　`build`で先ほど作成したDockerfileを使用してイメージをビルドします。
　`ports`でコンテナとホストのポートを紐付けます。ブラウザからアクセスするために必ず設定します。
　`volumes`でコンテナとホストのフォルダを紐付けます。PHPコンテナではPHPファイルの配置やログ参照に使用します。
　`links`でMySQLコンテナとのリンクを行います。MySQLにアクセスするための設定です。

`mysql`：
　MySQLコンテナの設定を行います。デバッグとは関係無いのでさらっとだけ説明します。
　`environment`コンテナの環境設定を行います。今回はユーザーやパスワードを設定しています。

`phpmyadmin`：
　phpMyAdminコンテナの設定を行います。こちらもパスワード等を設定します。
　その他の説明は割愛します。

# デバッグ実行の準備

Docker側の準備はすでに完了しているため、ホスト側(VSCode)の準備を行います。

## PHPソースの準備

`作業フォルダ/php`直下に`index.php`を作成します。

```bash
$ touch php/index.php
```
中身はこんな感じ。(PHP未経験者なのでソースは大目に見てください・・・)

```php
<?php

echo 'Hello World<br>';

// hostname, user, password, db name
$mysqli = new mysqli('mysql', 'docker', 'docker', 'app');

if ($mysqli->connect_error) {
  echo $mysqli->connect_error;
  exit();
} else {
    $mysqli->set_charset("utf8");
}

$sql = "SELECT id, name FROM test";
if ($result = $mysqli->query($sql)) {
    while ($row = $result->fetch_assoc()) {
        echo "ID:" . $row["id"] . " NAME:" . $row["name"] . "<br>";
    }
    $result->close();
}

$mysqli->close();
```

## デバッグ設定

VSCode上で左側のデバッグアイコン押下または[Shift + ⌘ + D]を押下してデバッグタブを開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/f3c4576a-0226-a1f1-b1cd-e38b25174bb8.png)

歯車アイコンを押下し、PHPを選択(無い場合は入力してください)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/e1ded74c-70fd-414a-dae2-cf9b50a93b70.png)

`lanch.json`が自動生成されるので、以下のように修正します。

```json
{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for XDebug",
      "type": "php",
      "request": "launch",
      "port": 9001,
      "pathMappings": {
        // Dockerコンテナのdocument root : 開発環境のdocument root
        "/var/www/html":"${workspaceFolder}/php/html" 
      }
    }
  ]
}
```

# いざ、デバッグ実行！！！

まずはコンテナを起動

```bash
$ docker-compose up -d
# 立ち上がっていることを確認
$ docker-compose ps
         Name                       Command               State               Ports
------------------------------------------------------------------------------------------------
php_study_mysql_1        docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
php_study_php_1          docker-php-entrypoint apac ...   Up      0.0.0.0:80->80/tcp
php_study_phpmyadmin_1   /run.sh phpmyadmin               Up      0.0.0.0:8080->80/tcp, 9000/tcp
```

MySQLの立ち上げに時間が掛かるので少し待ちます。

そしてVSCodeでブレイクポイントを設定します。
行番号の左側をクリックするだけ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/7aa32b29-f9ad-874e-9c2c-f7057c8ce3cb.png)

F5を押下してデバッガー起動
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/7fcf2991-efac-1d2f-cd70-2982604a4b7d.png)


ブラウザから http://localhost にアクセス

ブレイクポイントで止まった！！！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/199056/2d1a72f0-ae35-dda9-f587-5a8c19f392df.png)

以上です。
割と駆け足になってしまったので余裕があればもう少し詳細に記載します。