使用Docker、nginx、PHP7-FPM和Xdebug进行IDE调试

使用Docker、nginx、PHP7-FPM和Xdebug进行IDE调试,nginx,docker-compose,xdebug,php-7.2,fpm,Nginx,Docker Compose,Xdebug,Php 7.2,Fpm,我目前正在用docker compose在macOS上准备一个开发堆栈,以便能够在PHP7-FPM(端口:9000)和nginx(端口:80)服务器上使用Xdebug(端口:9009) 显然,配置还可以,但我无法通过IDE进行调试 以下是我的设置: 我的.env文件: APP_NAME=testeXdebug HOST_SERVER_NAME=myapp HOST_IP=docker.for.mac.localhost # Use docker.for.mac.localhost - for O

我目前正在用docker compose在macOS上准备一个开发堆栈,以便能够在PHP7-FPM(端口:9000)和nginx(端口:80)服务器上使用Xdebug(端口:9009)

显然,配置还可以,但我无法通过IDE进行调试

以下是我的设置:

我的
.env
文件:

APP_NAME=testeXdebug
HOST_SERVER_NAME=myapp
HOST_IP=docker.for.mac.localhost
# Use docker.for.mac.localhost - for OS X
# Use docker.for.win.localhost - for Windows
version: '3.5'

services:
  web:
    image: nginx:1.15.2
    ports:
      - '80:80'
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/default.conf:/etc/nginx/conf.d/default.conf'
      - '/tmp/${APP_NAME}/web:/var/log/nginx'
    env_file:
      - '.env'
    depends_on:
      - 'php-fpm'
    links:
      - 'php-fpm'

  php-fpm:
    build: './docker'
    ports:
      - '9000:9000'
      - '9009:9009'
    expose:
      - 9000
      - 9009
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/php-dev.ini:/usr/local/etc/php/conf.d/php-dev.ini'
      - '/tmp/${APP_NAME}/php-fpm:/var/log/xdebug'
    environment:
      XDEBUG_CONFIG: "remote_host=${HOST_IP}"
      PHP_IDE_CONFIG: "serverName=${HOST_SERVER_NAME}"
    env_file:
      - '.env'
; Xdebug
xdebug.default_enable = 1
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_port = 9009
xdebug.profiler_enable = 0
xdebug.idekey = PHPSTORM
xdebug.remote_handler = dbgp
xdebug.remote_mode = req
xdebug.remote_log = /var/log/xdebug/xdebug.log
server {
    listen          80;
    server_name     myapp;
    root            /usr/share/nginx/html;
    index           index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass    php-fpm:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }

    location ~ /\.ht {
        deny  all;
    }
}
Dockerfile
PHP7-FPM+Xdebug:

FROM php:7.2-fpm

RUN pecl install xdebug \
    && docker-php-ext-enable xdebug
docker compose.yml
文件:

APP_NAME=testeXdebug
HOST_SERVER_NAME=myapp
HOST_IP=docker.for.mac.localhost
# Use docker.for.mac.localhost - for OS X
# Use docker.for.win.localhost - for Windows
version: '3.5'

services:
  web:
    image: nginx:1.15.2
    ports:
      - '80:80'
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/default.conf:/etc/nginx/conf.d/default.conf'
      - '/tmp/${APP_NAME}/web:/var/log/nginx'
    env_file:
      - '.env'
    depends_on:
      - 'php-fpm'
    links:
      - 'php-fpm'

  php-fpm:
    build: './docker'
    ports:
      - '9000:9000'
      - '9009:9009'
    expose:
      - 9000
      - 9009
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/php-dev.ini:/usr/local/etc/php/conf.d/php-dev.ini'
      - '/tmp/${APP_NAME}/php-fpm:/var/log/xdebug'
    environment:
      XDEBUG_CONFIG: "remote_host=${HOST_IP}"
      PHP_IDE_CONFIG: "serverName=${HOST_SERVER_NAME}"
    env_file:
      - '.env'
; Xdebug
xdebug.default_enable = 1
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_port = 9009
xdebug.profiler_enable = 0
xdebug.idekey = PHPSTORM
xdebug.remote_handler = dbgp
xdebug.remote_mode = req
xdebug.remote_log = /var/log/xdebug/xdebug.log
server {
    listen          80;
    server_name     myapp;
    root            /usr/share/nginx/html;
    index           index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass    php-fpm:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }

    location ~ /\.ht {
        deny  all;
    }
}
php-dev.ini
文件:

APP_NAME=testeXdebug
HOST_SERVER_NAME=myapp
HOST_IP=docker.for.mac.localhost
# Use docker.for.mac.localhost - for OS X
# Use docker.for.win.localhost - for Windows
version: '3.5'

services:
  web:
    image: nginx:1.15.2
    ports:
      - '80:80'
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/default.conf:/etc/nginx/conf.d/default.conf'
      - '/tmp/${APP_NAME}/web:/var/log/nginx'
    env_file:
      - '.env'
    depends_on:
      - 'php-fpm'
    links:
      - 'php-fpm'

  php-fpm:
    build: './docker'
    ports:
      - '9000:9000'
      - '9009:9009'
    expose:
      - 9000
      - 9009
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/php-dev.ini:/usr/local/etc/php/conf.d/php-dev.ini'
      - '/tmp/${APP_NAME}/php-fpm:/var/log/xdebug'
    environment:
      XDEBUG_CONFIG: "remote_host=${HOST_IP}"
      PHP_IDE_CONFIG: "serverName=${HOST_SERVER_NAME}"
    env_file:
      - '.env'
; Xdebug
xdebug.default_enable = 1
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_port = 9009
xdebug.profiler_enable = 0
xdebug.idekey = PHPSTORM
xdebug.remote_handler = dbgp
xdebug.remote_mode = req
xdebug.remote_log = /var/log/xdebug/xdebug.log
server {
    listen          80;
    server_name     myapp;
    root            /usr/share/nginx/html;
    index           index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass    php-fpm:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }

    location ~ /\.ht {
        deny  all;
    }
}
nginx
default.conf
文件:

APP_NAME=testeXdebug
HOST_SERVER_NAME=myapp
HOST_IP=docker.for.mac.localhost
# Use docker.for.mac.localhost - for OS X
# Use docker.for.win.localhost - for Windows
version: '3.5'

services:
  web:
    image: nginx:1.15.2
    ports:
      - '80:80'
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/default.conf:/etc/nginx/conf.d/default.conf'
      - '/tmp/${APP_NAME}/web:/var/log/nginx'
    env_file:
      - '.env'
    depends_on:
      - 'php-fpm'
    links:
      - 'php-fpm'

  php-fpm:
    build: './docker'
    ports:
      - '9000:9000'
      - '9009:9009'
    expose:
      - 9000
      - 9009
    volumes:
      - '.:/usr/share/nginx/html'
      - './config/php-dev.ini:/usr/local/etc/php/conf.d/php-dev.ini'
      - '/tmp/${APP_NAME}/php-fpm:/var/log/xdebug'
    environment:
      XDEBUG_CONFIG: "remote_host=${HOST_IP}"
      PHP_IDE_CONFIG: "serverName=${HOST_SERVER_NAME}"
    env_file:
      - '.env'
; Xdebug
xdebug.default_enable = 1
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_port = 9009
xdebug.profiler_enable = 0
xdebug.idekey = PHPSTORM
xdebug.remote_handler = dbgp
xdebug.remote_mode = req
xdebug.remote_log = /var/log/xdebug/xdebug.log
server {
    listen          80;
    server_name     myapp;
    root            /usr/share/nginx/html;
    index           index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass    php-fpm:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }

    location ~ /\.ht {
        deny  all;
    }
}

然后,当通过浏览器在扩展处于活动状态时访问服务器时:

我得到这个调试日志(xdebug):


并使用以下命令设置带有调试扩展名的VSCode:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9009,
            "pathMappings": {
                "/usr/share/nginx/html": "${workspaceRoot}"
            }
        }
    ]
}
添加一些断点:

并在PhpStorm上执行以下操作:

使用docker compose的PhpStorm CLI解释器:

但是在开始监听PHP调试连接时我得到
端口9009正忙

IDE从不启动调试工具=(
我会错过什么?请帮帮我


在一些评论之后:

docker compose.yml

thiago@MA-TPR testeXdebug $ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                NAMES
735fc48fad63        nginx:1.15.2          "nginx -g 'daemon of…"   4 minutes ago       Up 4 minutes        0.0.0.0:80->80/tcp   testexdebug_web_1
b9b16af98fb5        testexdebug_php-fpm   "docker-php-entrypoi…"   4 minutes ago       Up 4 minutes        9000/tcp             testexdebug_php-fpm_1
thiago@MA-TPR testeXdebug $ 
并从xdebug获取此日志:

Log opened at 2018-08-12 00:56:39
I: Checking remote connect back address.
I: Checking header 'HTTP_X_FORWARDED_FOR'.
I: Checking header 'REMOTE_ADDR'.
I: Remote address found, connecting to 192.168.160.1:9009.
W: Creating socket for '192.168.160.1:9009', poll success, but error: Operation now in progress (29).
E: Could not connect to client. :-(
Log closed at 2018-08-12 00:56:39
从PHP容器执行
nc

root@b9b16af98fb5:/var/www/html# nc -zv docker.for.mac.localhost 9009
Warning: inverse host lookup failed for 192.168.65.2: Unknown host
docker.for.mac.localhost [192.168.65.2] 9009 (?) open
root@b9b16af98fb5:/var/www/html# 
但在开始监听PHP调试连接时,我得到的
端口9009正忙

不需要在Docker容器中公开Xdebug端口,根本不需要

如果您公开它,.Docker将侦听该端口并将所有连接转发到容器中。但必须侦听它的是IDE/VSCode/PhpStorm…因为连接到IDE的是Xdebug,而不是其他方式

先把它修好

xdebug.remote\u connect\u back=1

我建议关闭此选项并在
xdebug.remote\u host
docker.for.mac.localhost
)中指定实际主机

Xdebug通过
远程连接返回
选项检测到的IP(取决于我猜的设置和Docker的工作方式)很可能不是主机的IP。但这正是您需要的——这是您的IDE(PhpStorm)/编辑器(VSCode)运行的地方,Xdebug必须连接到的地方。

如果您使用的是“Docker for Mac”,则在xdebug配置文件中,也可以使用:

xdebug.remote_host = host.docker.internal
我想从容器连接到主机上的服务
主机的IP地址正在更改(如果您没有网络访问权限,则没有)。从18.03起,我们建议连接到特殊的DNS名称host.docker.internal,该名称解析为主机使用的内部IP地址。这是出于开发目的,在docker for Mac之外的生产环境中不起作用


网关也可以作为gateway.docker.internal访问。

让XDEBUG工作就像一次让10个盘子在棍子上旋转一样。可能存在的一个问题是,PhpStorm无法看到它报告的PHP.ini文件。您在“语言和框架”部分配置过PHP吗?另外,您构建文档的唯一目的是什么您是否希望能够使用XDEBUG进行本地开发,或者出于其他原因对使用Docker感兴趣?瞧,其他已经使用XDEBUG的替代方案如何?@MikeSchinkel我添加了一个带有解释器信息的图像。“但是在开始监听PHP调试连接时,我发现
端口9009正忙着
”当然,它很忙——你正在使用它。你在Docker中公开了9009?为什么?为什么?如果你公开了它。Docker侦听该端口并将所有连接转发到容器中。但是..必须侦听它的是IDE/VSCode/PhpStorm…因为连接到IDE的是Xdebug,而不是其他方式(请使用RTFM)。所以,请先解决这个问题,然后再试一次。@LazyOne Tks。所以我用您的建议更新了这个问题1)哪个应用程序在9009上侦听?在Mac上使用
sudolsof-nP-iTCP-sTCP:LISTEN
,在Windows上使用
netstat
。2)
xdebug.remote\u connect\u back=1
--我最好关闭此选项,并在
remote\u host
中指定主机--试试这种方法。Xdebug或nc每次尝试连接的IP地址都不一样--好吧,不应该是这样的。mac、windows和linux现在有一个通用设置,我认为是“host.docker.internal”,但如果没有您的第二部分响应,它就不起作用,也不是很重要,所以我在阅读中丢失了它,但是
xdebug.remote\u connect\u back=0也非常重要!!!我只是阅读你的设置,而不是周围的文字,所以我认为它必须设置为1,但它必须为零。考虑到各种各样的家伙在玩端口映射和expose,正如您正确地说的那样是无用的,因为php中的xdebug内部使用随机隐藏端口,9000混凝土端口是远程端口。否则,感谢您的帮助。因此xdebug.remote\u connect\u back=0在windows上也是必需的,尽管在linux上我有过不需要禁用它的经验。