背景
在本地环境下,我的项目运行在 Docker 容器中,并使用 Guzzle 进行 HTTP 请求。然而,在访问某些 HTTPS 资源时,遇到了如下错误:

GuzzleHttp\Exception\ConnectException: cURL error 35: OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection
这个错误表示 Guzzle 在建立 SSL 连接时失败,通常与 SSL 证书、cURL 配置或网络环境有关。
问题排查过程
1. 检查目标服务器 SSL 证书
首先,我们尝试在 Docker 容器内运行以下命令来手动测试 SSL 连接:
openssl s_client -connect example.com:443
如果服务器的证书无效或不受信任,会在这里报错。但经过测试,目标服务器的证书是有效的。
2. 更新 Docker 容器内的 SSL 证书
有时候,Docker 容器内缺少最新的 CA 证书,可能会导致 SSL 连接失败。因此,我们进入容器并更新证书:
docker exec -it <container_id> sh
# 对于 Alpine Linux
apk add --no-cache ca-certificates
update-ca-certificates
# 对于 Debian/Ubuntu
apt update && apt install -y ca-certificates
update-ca-certificates
但执行后仍然无法解决问题。
3. 强制 Guzzle 使用特定 TLS 版本
为了排除 TLS 版本兼容性问题,我们尝试在 Guzzle 配置中强制指定 TLS 版本:
$client = new \GuzzleHttp\Client([
'curl' => [
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2, // 或者 CURL_SSLVERSION_TLSv1_3
],
]);
但仍然无效。
4. 运行 cURL 手动测试
在容器内运行:
curl -v https://example.com
发现 cURL error 35
仍然存在,这说明问题不在 Guzzle,而是网络环境。
5. 发现问题根源:Docker Desktop 代理
经过深入排查,我们发现 Windows 上的 Docker Desktop 在 Settings -> Resources -> Proxies 里配置了代理。这导致 Docker 容器中的所有网络请求都会经过代理,而这个代理可能无法正确处理 HTTPS 连接。
解决方法:
- 打开 Docker Desktop 设置
- 进入 Resources -> Proxies
- 清空代理设置
- 重启 Docker Desktop
6. 问题解决
关闭代理后,重新运行 curl
命令,HTTPS 请求恢复正常,Guzzle 也能成功连接目标服务器。
总结
如果在 Docker 容器中遇到 Guzzle 或 cURL 的 SSL 连接错误,建议按照以下步骤排查:
- 检查目标服务器的 SSL 证书 是否有效。
- 更新 Docker 容器内的 CA 证书 (
ca-certificates
)。 - 尝试指定 TLS 版本 (
CURLOPT_SSLVERSION
)。 - 手动运行 cURL 测试 以确认是否是 Guzzle 代码问题。
- 检查 Docker Desktop 是否配置了代理,如果有,尝试关闭代理并重启 Docker。
最终发现是 Docker 代理配置的问题,希望对遇到类似问题的朋友有所帮助!
正文完