You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker化PHP项目加载外部WSDL报SOAP-ERROR问题求助

问题:Docker化PHP项目(WSL+Windows10)中SOAP WSDL加载失败

环境概述

  • 运行环境:WSL Linux(宿主机Windows10)下的Docker PHP项目
  • 访问外部SOAP服务需通过认证代理:
    • 代理主机:private_proxy,端口:8000
    • 代理用户名:private,密码:private
  • 加载WSDL地址http://myprivateurl/ressources/services/service?wsdl时触发错误:

    SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://myprivateurl/ressources/services/service?wsdl' : failed to load external entity

已尝试的排查步骤

  1. Docker Compose中配置代理环境变量:
groomrhv2-php:
  build:
    context: './.docker/php'
  depends_on:
    - postgresql
  image: ${PROJECT_NAME}-php
  container_name: ${PROJECT_NAME}-php
  volumes:
    - "./:/var/www/html:cached"
    - "./.docker/php/php.ini:/usr/local/etc/php/php.ini"
    - "./.docker/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini"
    - "./.docker/php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini"
    - "./.docker/php/xdebug.log:/tmp/xdebug.log"
  privileged: true
  environment:
    - PHP_IDE_CONFIG=serverName=groomrhv2-php
    - http_proxy=http://private_proxy:8000
    - https_proxy=http://private_proxy:8000
    - HTTP_PROXY_AUTH=private:private
    - no_proxy=localhost,127.0.0.1
  1. 验证容器内DNS解析与网络连通性
  2. 容器内curl访问WSDL地址报错:
docker exec -ti php_container bash
curl http://myprivateurl/ressources/services/service?wsdl

curl: (6) Could not resolve host

  1. 禁用WSDL缓存:ini_set('soap.wsdl_cache_enabled', 0);
  2. 实现SOAP错误捕获逻辑
  3. PHP代码中配置代理参数创建自定义SOAP客户端soapClientSecure:
private function construitClientSoap(string $sWsdl, SaeContratService $contratService)
{
    $classmap = array(
        'rechercheResponseType' => rechercheResponse::class,
        'rechercheNbResResponseType' => rechercheNbResResponse::class,
        'listeResultatRechercheType' => resultats::class,
        'listeResultatRechercheNbResType' => resultats::class,
        'resultatRechercheType' => resultatRecherche::class,
        'metadonneeType' => metadonnee::class,
        'listeMetadonneeType' => metadonnees::class,
        'recuperationMetadonneesResponseType' => recuperationMetadonneesResponse::class,
        'listeMetadonneeDispoType' => listeMetadonneeDispo::class,
        'metadonneeDispoType' => metadonneeDispo::class,
    );
    $sLocation = substr(trim($sWsdl), 0, -5);

    $proxyHost = '****';
    $proxyPort = **;
    $proxyUsername = '****';
    $proxyPassword = '******!';

    $options = [
        //'location' => $sLocation,
        'trace' => 1,
        //'classmap' => $classmap,
        //'soap_version' => SOAP_1_2,
        'proxy_host' => $proxyHost,
        'proxy_port' => $proxyPort,
        'proxy_login' => $proxyUsername,
        'proxy_password' => $proxyPassword,
    ];
    $client = new soapClientSecure($sWsdl, $options);
    $client->setWssedoc($this->getWsseSecurityDocument($contratService));
    return $client;
}

执行代码仍报错:

SOAP-ERROR: Parsing WSDL: Couldn't load from '*privateurl?wsdl' : failed to load external entity "*privateurl?wsdl?wsdl" in /var/www/html//iGED/gedClient.php:l.99


解决方案与排查方案

1. 优先解决DNS解析问题

容器内curl报Could not resolve host是核心问题,先确认域名解析:

  • 进入容器查看DNS配置:cat /etc/resolv.conf,确保DNS服务器能解析myprivateurl和private_proxy(内网域名需指定内网DNS)。
  • 在Docker Compose中强制指定DNS服务器:
    groomrhv2-php:
      # ... 其他配置
      dns:
        - 192.168.1.100 # 替换为你的内网DNS
        - 8.8.8.8
    
  • 若代理主机名无法解析,在Docker Compose中添加host映射:
    groomrhv2-php:
      # ... 其他配置
      extra_hosts:
        - "private_proxy:10.0.0.5" # 替换为代理实际IP
    

2. 修正代理配置的完整性

Docker Compose代理变量优化

HTTP_PROXY_AUTH不是标准环境变量,需将认证信息嵌入代理URL:

environment:
  - http_proxy=http://private:private@private_proxy:8000
  - https_proxy=http://private:private@private_proxy:8000
  - no_proxy=localhost,127.0.0.1,postgresql # 内部服务跳过代理

PHP SOAP客户端配置补全

  • 确认代码中$proxyHost等参数为实际值(替换占位符****)。
  • 检查错误日志中的privateurl?wsdl?wsdl,说明sWsdl参数可能被重复拼接?wsdl,验证传入的WSDL地址是否已包含该后缀。
  • 手动添加stream_context强制指定代理:
    $context = stream_context_create([
        'http' => [
            'proxy' => 'tcp://private_proxy:8000',
            'request_fulluri' => true,
            'header' => "Proxy-Authorization: Basic " . base64_encode("$proxyUsername:$proxyPassword")
        ],
        'https' => [
            'proxy' => 'tcp://private_proxy:8000',
            'request_fulluri' => true,
            'header' => "Proxy-Authorization: Basic " . base64_encode("$proxyUsername:$proxyPassword")
        ]
    ]);
    
    $options = [
        // ... 原有参数
        'stream_context' => $context,
    ];
    

3. 测试WSDL可访问性

  • 容器内用带代理的curl测试:
    curl -x http://private:private@private_proxy:8000 http://myprivateurl/ressources/services/service?wsdl
    
    若成功返回WSDL内容,说明网络正常,问题在SOAP客户端配置;若失败,继续排查网络/代理权限。
  • 下载WSDL到本地,用本地路径创建客户端验证代码逻辑:
    $client = new soapClientSecure('/var/www/html/service.wsdl', $options);
    

4. 检查PHP环境配置

  • 确认容器已安装php-soap扩展:php -m | grep soap,未安装则在Dockerfile中添加(Debian/Ubuntu:apt-get install -y php-soap;Alpine:apk add php-soap)。
  • 检查allow_url_fopen是否开启:php -i | grep allow_url_fopen,确保值为On,否则无法加载远程资源。

内容的提问来源于stack exchange,提问作者Khaled Boussoffara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 19:40:13