EC-CUBE4.2/VSCode/Docker のデバッグ環境作成

本記事は EC-CUBE Advent Calendar 2023 17日目の記事です。

# はじめに

こんにちは。
株式会社テンダの島田と申します。
「ワンストップで業務効率化を支援」がテーマの会社で、私は主にシステム開発のマネジメントをしています。

私が関わるチームではEC-CUBEを扱ったプロジェクトが多くなってきましたが、
IDEとデバッグ方法が画一化されてなかったので
**統一化のための手順を社内でまとめてみた**ので皆様にも共有いたします。

EC-CUBE開発の基礎的な内容はドキュメントサイトがありますのでそちらを是非御覧ください。
https://doc4.ec-cube.net/
本記事はその中でも
[Docker Composeを使用してインストールする](https://doc4.ec-cube.net/quickstart/docker_compose_install)
こちらのページをベースにしております。

また、本記事作成時点の環境とバージョンは以下のとおりです。

- OS バージョン : MacBook Pro OS 13.4.1
- docker バージョン : 20.10.13, build a224086
- docker-compose バージョン : 1.29.2, build 5becea4c
- EC-CUBE バージョン : 4.2 (コミットID cae3bf93fe)
- VisualStudio Code (IDE) : 1.85.0

※ docker, git, VSCode の各種インストールについては各位でご準備ください。

# EC-CUBEの取得から動作確認まで

早速ですがgitコマンドを使って最新のEC-CUBEを取得します。
今回は作業フォルダを ``/opt/docker/eccube`` で行う想定で進めます。

```shell
# 作業フォルダ作成
$ mkdir /opt/docker/eccube
$ cd /opt/docker/eccube/
# git cloneする
$ git clone https://github.com/EC-CUBE/ec-cube.git .
```

クローン出来たらdocker起動します。

```shell
$ cd /opt/docker/eccube/
$ docker-compose -f docker-compose.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml up -d
Creating volume "eccube_mailcatcher-data" with local driver
Creating volume "eccube_var" with local driver
Creating volume "eccube_vendor" with local driver
Creating volume "eccube_node_modules" with local driver
Creating volume "eccube_mysql-database" with local driver
Pulling ec-cube (ghcr.io/ec-cube/ec-cube-php:8.1-apache)...
8.1-apache: Pulling from ec-cube/ec-cube-php
...
```

しばらく待つとセットアップが完了し、フロントや管理画面へのアクセスができるはずです。
なお、各ymlの意味はドキュメントサイトに詳細ありますが、ざっくりと以下と認識しておけばOKです。

- docker-compose.yml : 各種サービス利用の設定
- docker-compose.mysql.yml : MySQLを利用することが多いのでMySQL設定
- docker-compose.dev.yml : こちらを読み込んでおけばキャッシュせず常に変更を反映できる

アクセスできるはず。
フロントはドメインアクセスすれば表示されるはず。。
http://localhost:8080/
![2023-12-15_14-32-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/ace57e0c-2f3a-11bc-154f-23f033043339.png)
OK

管理画面も。
http://localhost:8080/admin/
(管理画面のID/PWDは docker-compose.mysql.yml に記載されています。)
![2023-12-15_14-32-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/06b48164-f3db-f040-c6e5-76edb1b05b57.png)

動作することを確認したら、一度停止しましょう。
ドキュメントサイトでは ``docker-compose down`` で停止、とありますが私の環境ではネットワーク絡みでエラーになります。

```sh
$ docker-compose down
Stopping eccube_ec-cube_1     ... done
Stopping eccube_mailcatcher_1 ... done
WARNING: Found orphan containers (eccube_mysql_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
Removing eccube_ec-cube_1     ... done
Removing eccube_mailcatcher_1 ... done
Removing network eccube_backend
ERROR: error while removing network: network eccube_backend id XXXXXXXX has active endpoints
```

ですので以下コマンドで停止させます。(上のメッセージにもある通り、オプションをつけて停止。)
```sh
# 停止コマンドは --remove-orphans オプションを付けて実施
$ docker-compose down --remove-orphans
Stopping eccube_ec-cube_1     ... done
Stopping eccube_mailcatcher_1 ... done
Removing orphan container "eccube_mysql_1"
Removing eccube_ec-cube_1     ... done
Removing eccube_mailcatcher_1 ... done
Removing network eccube_backend
# プロセスが終了したことを確認。問題なし。
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

# デバッグ用のdockerイメージをビルドする

先程のdocker環境はデバッグに関するライブラリ等が入っていません。
docker-compose.yml には以下のように記載されています。
```yml
services:
  ### ECCube4 ##################################
  ec-cube:
    ### ローカルでビルドする場合は以下のコマンドを使用します
    ## docker build -t ec-cube --no-cache --pull --build-arg TAG=8.1-apache .
    ## docker tag ec-cube ghcr.io/ec-cube/ec-cube-php:8.1-apache
    image: ${REGISTRY:-ghcr.io}/${IMAGE_NAME:-ec-cube/ec-cube-php}:${TAG:-8.1-apache}
```
デバッグのためxdebugとその設定を入れた環境をビルドします。

Dockerfileの編集↓
```diff
$ vi Dockerfile
$ git diff Dockerfile
diff --git a/Dockerfile b/Dockerfile
index ded4d2dc42..33a2b20e0f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -64,6 +64,9 @@ RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
 COPY dockerbuild/php.ini $PHP_INI_DIR/conf.d/
 COPY dockerbuild/docker-php-entrypoint /usr/local/bin/

+# Use xdebug
+RUN pecl install xdebug && docker-php-ext-enable xdebug
+
 RUN curl -sS https://getcomposer.org/installer \
   | php \
   && mv composer.phar /usr/bin/composer
```

php.iniの編集↓
```diff
$ vi dockerbuild/php.ini
$ git diff dockerbuild/php.ini
diff --git a/dockerbuild/php.ini b/dockerbuild/php.ini
index 6491889bd9..a5ff99cec7 100644
--- a/dockerbuild/php.ini
+++ b/dockerbuild/php.ini
@@ -4,3 +4,6 @@ opcache.memory_consumption=256
 realpath_cache_size = 4096K
 realpath_cache_ttl = 600
 memory_limit = 786M
+; for xdebug
+xdebug.start_with_request = yes
+xdebug.mode = debug
```

デバッグ用ymlの追加↓
```diff
$ cp docker-compose.yml docker-compose.xdebug.yml
$ vi docker-compose.xdebug.yml
$ diff docker-compose.yml docker-compose.xdebug.yml
25c25
<     image: ${REGISTRY:-ghcr.io}/${IMAGE_NAME:-ec-cube/ec-cube-php}:${TAG:-8.1-apache}
---
>     image: ${REGISTRY:-ghcr.io}/${IMAGE_NAME:-ec-cube/ec-cube-php}:${TAG:-8.1-apache-xdebug}
```

ここまで準備できたらビルドを実行する。

```sh
# docker buildの実行
$ docker build -t ec-cube --pull --build-arg TAG=8.1-apache .
# タグ付けの際 8.1-apache-xdebug とすることで使い分けしやすくする
$ docker tag ec-cube ghcr.io/ec-cube/ec-cube-php:8.1-apache-xdebug
```
※ 私の環境ではビルド完了まで5分くらい時間かかりました。共有まで。

ビルドとタグ付けが終わったらイメージの状況を確認してみます。

```sh
$ docker images
REPOSITORY                        TAG                 IMAGE ID       CREATED          SIZE
ec-cube                           latest              b1aea8f8740c   50 seconds ago   907MB
ghcr.io/ec-cube/ec-cube-php       8.1-apache-xdebug   b1aea8f8740c   50 seconds ago   907MB
ghcr.io/ec-cube/ec-cube-php       8.1-apache          1c12f61255b7   10 days ago      840MB
```

問題なさそうです。
使い分けとしては以下のイメージです。
- TAG:8.1-apache → デバッグを伴わない確認
- TAG:8.1-apache-xdebug → デバッグを使った開発

# デバッグ用のイメージを使ったdocker起動

デバッグ用イメージを使って再度起動します。
```sh
$ docker-compose -f docker-compose.xdebug.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml up -d
Creating network "eccube_backend" with driver "bridge"
Creating eccube_mysql_1       ... done
Creating eccube_mailcatcher_1 ... done
Creating eccube_ec-cube_1     ... done
```
問題ないですね。
``docker ps`` で状態確認しても問題なし。
```sh
$ docker ps
CONTAINER ID   IMAGE                                           COMMAND                  CREATED          STATUS                    PORTS                                            NAMES
69c65a4de7e1   ghcr.io/ec-cube/ec-cube-php:8.1-apache-xdebug   "docker-php-entrypoi…"   12 seconds ago   Up 10 seconds (healthy)   0.0.0.0:8080->80/tcp, 0.0.0.0:4430->443/tcp      eccube_ec-cube_1
38735586f86f   mysql:5.7                                       "docker-entrypoint.s…"   16 seconds ago   Up 14 seconds (healthy)   33060/tcp, 0.0.0.0:13306->3306/tcp               eccube_mysql_1
28bc53a5717d   schickling/mailcatcher                          "mailcatcher --no-qu…"   16 seconds ago   Up 15 seconds             0.0.0.0:1025->1025/tcp, 0.0.0.0:1080->1080/tcp   eccube_mailcatcher_1
```

# VSCodeでのデバッグ

最後のステップです。VSCodeでデバッグをします。
先程の手順の続きで、dockerはデバッグ用のイメージを立ち上げた状態でVSCodeを起動します。
フォルダーを開く → 作業フォルダ と選択すると、「コンテナで再度開くか」を問われます。
「コンテナーで再度開く」を選択します。
![2023-12-15_02-32-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/2c35d8b1-180f-23b4-f85c-7bf717d8894f.png)

画面が切り替わり、開発コンテナの構成に切り替わったことがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/a6c78677-8c61-d9c4-9325-b968231ec387.png)
続いて、左パネルの「拡張機能」を開き、検索ボックスに
``@category:debuggers``
と入力します。
xdebug.org提供の「PHP Debug」が表示されると思うのでこれをインストールします。
![2023-12-15_02-35-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/71e2ea89-ee2c-152e-4237-645628521200.png)
インストールが完了したら、次に左パネルの「実行とデバッグ」を開きます。
launch.jsonファイルを作成→PHPと選択するとファイルが生成されます。
![2023-12-15_02-35-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/3297a19a-936b-b1be-c91e-78e403869549.png)
このファイルは編集不要です(デフォルトでポート9003になっているはず)

あとは左上のパネル「実行とデバッグ」→「Listen for Xdebug」の再生ボタンを押下するとデバッグが開始されます。

試しに管理画面から商品管理→ID2のチェリーアイスサンドの商品編集に遷移するとブレークポイントでウォッチできるか見てみます。
``ProductController.php`` 428行目あたりからのedit関数が商品編集に関する処理です。
430行目にブレークポイント貼って、画面遷移したらブレークポイントで止まるかと思います。
![2023-12-15_02-46-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1353602/a0355710-1315-0a25-6467-78a347fc7cdf.png)
``$id`` にカーソルを合わせたら「2」となっていることがわかるかと思います。
あるいはウォッチ式に「$id」と入力しても値の箇所が「2」となっているかと思います。
ということでブレークポイントで止まることと、その中身の変数等の値が見える状態になりました。

開発効率がこれで上げられるかと思います。

# おわりに

本記事は、EC-CUBEデバッグのスタンダードを見つけきらなかったのでチームに向けて作成したフローを少しだけ見栄えを意識したものです。
皆様のベターアンサーを是非教えてください。

たとえば本記事記載のVSCodeでの開発コンテナに入った際の挙動ですが、一度開発コンテナから抜けて再度開いた場合は、再度拡張機能xdebugのインストールが必要となります。
毎度インストールを実施してますが、より良い方法があるはず、、

以上です。