解决 Docker Desktop 代理导致的 Guzzle SSL 连接错误

背景

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

解决 Docker Desktop 代理导致的 Guzzle SSL 连接错误
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 连接错误,建议按照以下步骤排查:

  1. 检查目标服务器的 SSL 证书 是否有效。
  2. 更新 Docker 容器内的 CA 证书 (ca-certificates)。
  3. 尝试指定 TLS 版本 (CURLOPT_SSLVERSION)。
  4. 手动运行 cURL 测试 以确认是否是 Guzzle 代码问题。
  5. 检查 Docker Desktop 是否配置了代理,如果有,尝试关闭代理并重启 Docker。

最终发现是 Docker 代理配置的问题,希望对遇到类似问题的朋友有所帮助!

正文完
 0
评论(没有评论)
验证码