调试Docker应用时Xdebug在curl_exec处挂起的问题排查
我在Windows11上用Docker部署了包含REST API的网站,使用NetBeans配合Xdebug 3调试。非调试状态下网站运行正常,但调试时,执行到curl_exec调用同服务器API的代码时,程序无报错挂起,即使删除所有断点也会出现该问题。用WAMPServer调试一切正常,Postman调用API也无异常。
我的配置如下:
php.ini中的Xdebug 3配置
# Xdebug 3 xdebug.mode=debug # Client stuff xdebug.discover_client_host=1 xdebug.client_host=host.docker.internal xdebug.client_port=9003 xdebug.idekey="netbeans-xdebug" # Making sure we have some time xdebug.connect_timeout_ms = 6000 ;xdebug.log_level : 0 Criticals, 1 Connection, 3 Warnings, 5 Communication, 7 Information, 10 Debug Breakpoint xdebug.log_level=7 xdebug.log=/var/log/xdebug/xdebug.log # Some error and log settings xdebug.force_display_errors=1 xdebug.show_error_trace=1 xdebug.show_exception_trace=1 xdebug.show_local_vars=0
Docker Compose web服务配置
# This is the container for the Apache server web: # The location of the Dockerfile build: context: './bin/php' # A file containing sensitive information env_file: ".env" # The name for this container container_name: "server" # If anything goes wrong, restart the web server restart: "always" # Using both port 80 on the host and the container ports: - "80:80" # We want the database to be started before the server can start depends_on: - database volumes: # The 'web' directory will be mapped to the container directory "/var/www" - ./web:/var/www - ./settings.conf:/var/settings.conf # These are config files mapped to the VMs config files - ./config/php/php.ini:/usr/local/etc/php/php.ini - ./config/vhosts:/etc/apache2/sites-enabled # These are log directories mapped to the VMs log directories - ./logs/apache2:/var/log/apache2 - ./logs/xdebug:/var/log/xdebug environment: # Settings for the Apache webserver APACHE_DOCUMENT_ROOT: /var/www # Settings for phpMyAdmin PMA_PORT: 8080 # Settings for the MySQL database MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} MYSQL_DATABASE: database HOST_MACHINE_MYSQL_PORT: 3306 # Settings for XDEBUG XDEBUG_CONFIG: "client_host=host.docker.internal remote_port=9003" extra_hosts: - "host.docker.internal:host-gateway"
网站Dockerfile基于PHP:8.2-apache镜像构建,已安装Xdebug。
这个问题的核心是:调试主请求时,curl_exec发起的同服务器API请求也触发了Xdebug调试,而IDE默认只能处理一个调试连接,导致子请求等待IDE响应,进而整个程序挂起。
可以通过以下几种方式解决:
限制Xdebug仅在手动触发时启动
修改php.ini中的xdebug.mode和xdebug.start_with_request:xdebug.mode=develop,debug xdebug.start_with_request=trigger这样只有当请求中包含
XDEBUG_SESSION=netbeans-xdebug参数(或IDE自动添加的调试Cookie)时,Xdebug才会启动调试。curl发起的内部请求不会自动触发调试,避免阻塞。在curl请求中禁用Xdebug
若不想修改全局配置,可在curl请求里添加XDEBUG_SESSION=off的Header,强制关闭子请求的Xdebug:$ch = curl_init('http://your-api-url'); curl_setopt($ch, CURLOPT_HTTPHEADER, ['XDEBUG_SESSION: off']); // 其他curl配置 $response = curl_exec($ch);检查Xdebug日志确认问题
查看/var/log/xdebug/xdebug.log,如果发现有两个调试连接请求(主请求和curl的子请求),即可确认是该原因。日志里会有类似Connecting to configured address/port: host.docker.internal:9003的重复条目。统一Xdebug配置,避免冲突
Docker Compose的XDEBUG_CONFIG环境变量和php.ini中的配置重复,建议只保留一处配置,比如删除php.ini中的xdebug.client_host和xdebug.client_port,用环境变量统一控制,避免配置冲突。
内容的提问来源于stack exchange,提问作者Zoë van den Berg

