3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Xdebugを入れたDocker上のPHP LaravelのWebアプリをVSCodeでステップ実行させるサンプル (WSL2)

Last updated at Posted at 2021-12-18

背景

Laravelをはじめ、PHPのWebアプリケーション開発において、デバッグをする際、

var_dump(○○○○○);

のように、変数をブラウザ上に出力する方法を取られることがあります。

しかし、この方法では、

  • 条件分岐やループ等の処理の流れを追うことは難しい。
    ※追うためには多くの個所でvar_dump等の出力を入れなければならない。
  • 文字列以外のデータ(日付、リスト、辞書など)を読みやすい形式で出力されるとは限らない。
    ※表示用のフォーマットを設定したり、JSON形式にするなど、手間がかかる。
  • デバッグ後にvar_dump等のコードを確実に削除しなければならない。
    ※万一、削除漏れがあったままリリースすると、内部的な情報が表示されてしまう。

などの問題があり、効率的なデバッグをすることができませんよね。
開発している方の中にも、苦労されている方もいらっしゃると思います。

一方で、Xdebug等によるデバッグ環境構築の手順、特に、Dockerコンテナでの環境での手順は、あまりまとまっていないのようです。
社内の開発メンバーからも、手順を知っている人がいないか?という質問がありましたが、手順を把握しているメンバーはいませんでした。

そこで、実際にデバッグ環境を作ってみることにしました。

はじめに

このサンプルは、DockerでPHPおよびNGINXのコンテナを作成し、PHPのコンテナにXdebugをインストールし、ローカルのVSCodeでステップ実行させるものです。

なお、今回は、Windows 10にWSL2(Windows Subsystem for Linux 2)でUbuntu 20.04をインストールし、その上にDockerおよびDocker Composeをインストールした環境を使用しています。

Macや、Docker Desktop for Windows等の環境については、動作するかは不明です。申し訳ありませんがご了承ください。
※Docker Compose実行シェルスクリプトのユーザー・グループの情報を変更することで、動作する可能性がありますので、よろしければお試しください。

サンプルについて

なお、この記事のために作成したサンプルは、GitHubの私のリポジトリ
https://github.com/murakami0923/laravel-remote-debug-sample
にあります。

全体条件や使用方法など、詳細は、こちらのリポジトリのREADME.mdをご参照ください。

【解説】全体の構成の概要

構成図

全体の構成を図にまとめます。

002-001_environment.png

Docker Composeで下記3つのコンテナを起動します。

  • NGINX
  • PHP-FPM(Laravelアプリケーション)
  • MariaDB

PHPの処理の流れ

このとき、NGINXコンテナのnginx-app.confファイルで、\*.phpへのアクセスの場合、FastCGIでPHP-FPM(Laravelアプリケーション)のコンテナの9000ポートへアクセスを渡すように設定します。

その後、開発者がWebブラウザでNGINXにアクセスすると、PHPへのアクセスの場合、PHP-FPMコンテナに処理が渡り、処理後にレスポンスを開発者のWebブラウザに返ります。

PHP-FPMコンテナ上でのデバッグ

また、PHP-FPM内のLaravelアプリケーションにはXdebugをインストール・設定し、開発者のVSCodeにRemote Containersの拡張機能をインストール・設定します。

その後、開発者がWSL2でVSCodeを開き、続いて、Remote Containersに設定したコンテナを開くと、コンテナ上にVSCode Serverがインストールされ、自動的に開きます。
次に、XCodeのデバッグ設定をしてデバッグを実行すると、コンテナ上のVSCode ServerがXdebugに接続し、デバッグ可能となります。

VSCode Serverで、Controller等にブレークポイントを設定し、Webブラウザでサイトにアクセスすると、ブレークポイントで処理が止まり、ステップ実行しながら変数等の状態を確認することができます。

Docker Composeのボリュームについて

Laravelアプリケーション(laravel-appディレクトリ)をボリュームに設定します。

NGINX、PHP-FPMの書くコンテナにおいて、/var/www/htmlがRootディレクトリとなるため、laravel-appをボリュームとして設定します。

なお、WSL2 Ubuntuで使用しているユーザーのuidとアプリケーション実行ユーザーのuidが合わないと、ディレクトリやファイルへの読取り・書込み・実行の権限が、Laravelアプリケーションを正しく実行できないことがあります。

PHP-FPMのアプリケーション実行ユーザは、デフォルトではwww-data(uid : 33)となっていますが、WSL2ユーザーのユーザーとグループをPHP-FPMコンテナ内に作成し、そのユーザーでアプリケーションを実行するようにしています。

【解説】Docker定義

NGINXコンテナ定義

定義:docker/laravel-remote-debug-sample-nginx

LaravelのPHPアプリケーションへアクセスが来た時に、PHP-FPMコンテナに処理を渡すための設定が必要になるので、下記設定ファイルにて定義しています。

設定ファイル:nginx-app.conf

server {
    listen 80;
 
    root  /var/www/html/public;
    index index.php index.html index.htm;
 
    access_log /var/log/nginx/app-access.log;
    error_log  /var/log/nginx/app-error.log;

     # 全てのアクセスに対しての処理。左からドキュメントルート配下を参照する。以下の場合は3つのステップを踏んでいる
    # 1) アクセスがきたパスの静的ファイルが存在するか
    # 2) アクセスがきたパスのディレクトリが存在するか(見つかったらその中の indexを参照する)
    # 3) 上の二つがない場合、index.phpのファイルとする(Laravelに処理を任せる)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    # 静的ファイルの時の処理。正規表現によるパターンマッチングが使える
    location ~* \.(jpg|jpeg|gif|css|png|js|ico|svg)$ {
        expires 30d; # キャッシュの設定。クエリーを変更の処理がしっかりさmaxでもいい。今回は30日
        log_not_found off; # ログを出さない。publicサーバは攻撃に晒されていてログがたくさん出てしまうため
        access_log off; # 同じ理由でアクセスログも見えないようにしている
    }
 
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass   laravel-remote-debug-sample-app:9000;
        fastcgi_index  index.php;
 
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO $fastcgi_path_info;
    }
}

このファイルをCOPYし、コンテナ内に設置するよう、Dockerfileに記載しています。

COPY nginx-app.conf /etc/nginx/conf.d/
RUN mv /etc/nginx/conf.d/nginx-app.conf /etc/nginx/conf.d/app.conf

PHP-FPMコンテナ定義

定義:docker/laravel-remote-debug-sample-app

Xdebugをインストールするよう、Dockerfileに記載しています。

COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN install-php-extensions gd xdebug

また、Xdebugの設定ファイルを作成します。

設定ファイル:docker-php-ext-xdebug.ini

zend_extension=xdebug
xdebug.client_host = localhost
xdebug.start_with_request = yes
xdebug.mode = debug
; port 番号はデフォルトで9003番ですがわかりやすいように明示的に書いています。9003ではなくても空いているポートなら大丈夫です。
; 後述する .devcontainer/devcontainer.json に書く port と同じにしてください。
xdebug.client_port = 9003
xdebug.log = /var/log/xdebug.log

この設定ファイルを設置するよう、Dockerfileに記載しています。

RUN mv /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini /tmp/docker-php-ext-xdebug.ini.org
COPY docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

※設定ファイルの中で指定しているポート番号で、Remote Containersやデバッグの際に接続しています。

【解説】PHP-FPM実行ユーザーの作成

実行する環境によって、ユーザー名・グループ名が異なるため、コンテナ実行時のシェルスクリプトで、ユーザーの作成を定義しています。

まず、Docker Composeで、環境変数を渡すよう、定義しています。

定義ファイル:docker-compose.yaml(抜粋)

    app:
        ~(中略)~
        environment:
            - USER_NAME
            - USER_ID
            - GROUP_NAME
            - GROUP_ID

また、Docker Compose実行の際、WSL2 Ubuntuのユーザー情報、グループ情報を変数に入れてから実行することで、コンテナに環境変数として渡されます。

Docker Compose実行シェルスクリプト:start-docker-compose.sh

USER_NAME=$(id -un) USER_ID=$(id -u) GROUP_NAME=$(id -gn) GROUP_ID=$(id -g) docker-compose up -d

※Mac等、違う環境で実行する場合は、この部分を変更してください。
(laravel-appディレクトリ以下の所有者と同じユーザーでご指定ください。)

更に、PHP-FPMコンテナ実行時のシェルスクリプトで、ユーザーを作成するようにしています。

rootユーザーのシェルスクリプト:startup-root.sh(抜粋)

このシェルスクリプトで、アプリケーション実行ユーザーとグループを作成しています。
また、

#!/bin/bash

# 環境変数で渡されたユーザー、グループ情報をechoする。(アプリケーション実行ユーザー)
echo ${USER_NAME}
echo ${USER_ID}
echo ${GROUP_NAME}
echo ${GROUP_ID}

# 環境変数で渡されたユーザー、グループを作成する。
groupadd -g ${GROUP_ID} ${GROUP_NAME} 
useradd -u ${USER_ID} -g ${GROUP_ID} -m -s /bin/bash ${USER_NAME}

※作成前にechoすることで、Dockerホスト(WSL2 Ubuntu)で、下記コマンドを実行すると、正しくユーザーとグループが作成されたか、確認できます。

docker logs laravel-remote-debug-sample-app

次に、アプリケーション実行ユーザーのシェルスクリプトを設置して実行しています。

rootユーザーのシェルスクリプト:startup-root.sh(抜粋)

# startup-user.shを作成したユーザーのホームディレクトリへ複製し、所有者を変更する。
/bin/cp /root/startup-user.sh /home/${USER_NAME}/
chown ${USER_NAME}:${GROUP_NAME} /home/${USER_NAME}/startup-user.sh

# startup-user.shを実行する。
echo "call ${USER_NAME} startup script"
su - ${USER_NAME} -c "/home/${USER_NAME}/startup-user.sh"
echo "end ${USER_NAME} startup script"

アプリケーション実行ユーザーでは、Laravelに必要なcomposerのパッケージをインストールし、.envのAPP_KEYを生成しています。

アプリケーション実行ユーザーのシェルスクリプト:startup-user.sh

#!/bin/bash

cd /var/www/html/

# composerのパッケージをインストールする。
composer install

# .envのAPP_KEYを生成する。
php artisan key:generate
php artisan cache:clear
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?