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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:52:08