Docker环境下FrankenPHP/Caddy无法通过内部域名用cURL访问问题
我有一个运行API Platform 4的Symfony 7.1应用(容器名为core),供其他Docker化应用读写数据库及执行业务逻辑。该应用基于FrankenPHP 1.2.5 / PHP 8.3部署,另有一个Symfony应用容器(名为app),两者通过同一Docker网络连接,分别在不同compose.yml中配置。
我尝试通过内部域名访问core的API,示例代码如下:
<?php // 在控制器中 public function testAction(HttpClientInterface $client): Response { $data = $client->request( 'GET', 'https://core/api/report/company/statistics', // 测试时添加,但无效 ['verify_host' => false, 'verify_peer' => false] ); }
但收到错误:
OpenSSL/3.1.6: error:0A000438:SSL routines::tlsv1 alert internal error for "https://core/api/report/company/statistics".
进入app容器执行curl命令:
var/www/html # curl --insecure -vI https://core/api/report/company/statistics * Host core:443 was resolved. * IPv6: (none) * IPv4: 172.24.0.12 * Trying 172.24.0.12:443... * Connected to core (172.24.0.12) port 443 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS alert, internal error (592): * OpenSSL/3.1.6: error:0A000438:SSL routines::tlsv1 alert internal error * Closing connection curl: (35) OpenSSL/3.1.6: error:0A000438:SSL routines::tlsv1 alert internal error
执行openssl命令的结果:
/var/www/html # openssl s_client -connect core:443 CONNECTED(00000003) 08EB0452797F0000:error:0A000438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:ssl/record/rec_layer_s3.c:1605:SSL alert number 80 --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 7 bytes and written 293 bytes Verification: OK --- New, (NONE), Cipher is (NONE) This TLS version forbids renegotiation. No ALPN negotiated Early data was not sent Verify return code: 0 (ok) ---
当前处于开发阶段,我可忽略SSL错误,但即使禁用验证仍无法解决问题。请问是否有人遇到过FrankenPHP/Caddy在开发中忽略SSL问题的类似情况?
出现这个问题的核心原因是FrankenPHP/Caddy默认不会为内部Docker域名自动配置有效的SSL证书,甚至可能没在内部端口开启HTTPS监听——禁用证书验证只是跳过了证书有效性检查,但握手阶段因为服务端没有证书或者配置错误,直接抛出了内部错误。
下面是几种快速解决的方法:
1. 改用HTTP访问内部API(开发环境首选)
开发阶段没必要在内部Docker网络用HTTPS,直接切换到HTTP:
$data = $client->request( 'GET', 'http://core/api/report/company/statistics' );
FrankenPHP默认在开发模式下会同时监听80(HTTP)和443(HTTPS)端口,所以这个方法无需额外配置,直接生效。
2. 为内部域名配置Caddy自签名证书
如果一定要用HTTPS,修改core应用的Caddyfile,为core域名生成自签名证书:
core:443 { tls internal # 生成自签名证书 # 保留原有配置,比如: frankenphp php_fastcgi unix:///run/php/php8.3-fpm.sock root public }
重启core容器后,Caddy会自动生成证书,此时再用原来的HTTPS请求,配合verify_host和verify_peer参数就能正常访问。
3. 确保FrankenPHP开启HTTP监听
如果core容器的启动命令只开启了HTTPS,手动添加HTTP端口:
在core的compose.yml中修改命令:
services: core: # 其他配置 command: frankenphp run --http 0.0.0.0:80 --https 0.0.0.0:443
这样内部容器可以走HTTP,外部请求继续用HTTPS。
排查小技巧
- 用
docker exec core curl http://localhost/api/report/company/statistics在core容器内部测试API是否正常 - 查看
core容器日志,确认Caddy/FrankenPHP是否有证书生成失败或端口监听错误的信息 - 用
docker network inspect <你的网络名>确认app和core在同一个网络中
内容的提问来源于stack exchange,提问作者fistameeny

