无法建立到Docker容器内WebSocket服务的连接(最简示例)
Docker容器内WebSocket服务无法外部连接问题排查
问题描述
无法建立到Docker容器内WebSocket服务器的连接,但其他协议(如NATS)可正常连通。例如容器中运行的nats-server,端口422提供NATS服务、8080提供WebSocket服务,执行docker run -p 4222:422 -p 8080:8080 ...后,NATS客户端能连接nats://localhost:4222,但WebSocket客户端连接ws://localhost:127.0.0.1失败,报错无有效信息。
最简复现示例
使用websocat搭建最小测试环境,Dockerfile内容如下:
FROM alpine:3.20 RUN apk add websocat EXPOSE 9000 CMD ["websocat", "-v", "-v", "-v", "-s", "9000", "-P", "Working"]
构建与运行
$ docker build . --tag websocat [...输出省略...] $ docker run -p 9000:9000 websocat
服务器启动日志显示监听地址:
Listening on ws://127.0.0.1:9000/ [DEBUG websocat::lints] Substituting StdioClass with AsyncStdioClass at the right [INFO websocat::lints] Auto-inserting the line mode [DEBUG websocat] Done third phase of interpreting options. [DEBUG websocat] Done fourth phase of interpreting options. [DEBUG websocat] Preparation done. Now actually starting. [DEBUG websocat::sessionserve] Serving Message2Line(WsServer(TcpListen(127.0.0.1:9000))) to BroadcastReuser(Line2Message(AsyncStdio)) with Options { ... } [DEBUG websocat::net_peer] Listening TCP socket
端口映射验证
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4325c321f2c3 websocat "websocat -v -v -v -…" About an hour ago Up About an hour 0.0.0.0:9000->9000/tcp great_curran
外部连接失败现象
websocat客户端连接
$ websocat -v -v -v ws://127.0.0.1:9000 [INFO websocat::lints] Auto-inserting the line mode [DEBUG websocat] Done third phase of interpreting options. [DEBUG websocat] Done fourth phase of interpreting options. [DEBUG websocat] Preparation done. Now actually starting. [DEBUG websocat::sessionserve] Serving Line2Message(ThreadedStdio) to Message2Line(WsClient("ws://127.0.0.1:9000/")) with Options { ... } [INFO websocat::stdio_threaded_peer] get_stdio_peer (threaded) [DEBUG websocat::sessionserve] Underlying connection established [INFO websocat::ws_client_peer] get_ws_client_peer [INFO websocat::net_peer] Connected to TCP 127.0.0.1:9000 websocat: WebSocketError: WebSocket protocol error websocat: error running
curl连接
$ curl -v -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: 127.0.0.1:9000" -H "Origin: http://127.0.0.1" http://127.0.0.1:9000 * Trying 127.0.0.1:9000... * Connected to 127.0.0.1 (127.0.0.1) port 9000 > GET / HTTP/1.1 > Host: 127.0.0.1:9000 > User-Agent: curl/8.7.1 > Accept: */* > Connection: Upgrade > Upgrade: websocket > Origin: http://127.0.0.1 > * Request completely sent off * Empty reply from server * Closing connection curl: (52) Empty reply from server
关键现象:两种外部连接方式下,websocat服务器端均未记录任何连接尝试。
容器内部连接正常
在容器内执行客户端连接:
$ docker exec 4325c321f2c3 websocat -v ws://127.0.0.1:9000/ [INFO websocat::lints] Auto-inserting the line mode [INFO websocat::ws_client_peer] get_ws_client_peer [INFO websocat::net_peer] Connected to TCP 127.0.0.1:9000 [INFO websocat::ws_client_peer] Connected to ws [INFO websocat::sessionserve] Forward finished Working [INFO websocat::ws_peer] incoming None [INFO websocat::sessionserve] Reverse finished [INFO websocat::sessionserve] Both directions finished
服务器端会正常记录连接:
[INFO websocat::net_peer] Incoming TCP connection from Some(127.0.0.1:46268) [DEBUG websocat::sessionserve] Underlying connection established [INFO websocat::sessionserve] Serving 1 ongoing connections [INFO websocat::ws_server_peer] Incoming connection to websocket: / [...其余日志省略...]
测试环境
- MacOS 15.1.1(Intel),Docker 27.3.1
- Ubuntu 24.04,Docker 27.4.0
问题原因与解决方案
核心问题是WebSocket服务仅监听容器内的127.0.0.1地址,该地址仅能接收容器内部发起的连接,外部请求通过端口映射进入后无法被服务接收。
修复方法
修改Dockerfile中的CMD命令,让websocat监听0.0.0.0:9000(绑定容器所有网络接口):
FROM alpine:3.20 RUN apk add websocat EXPOSE 9000 CMD ["websocat", "-v", "-v", "-v", "-s", "0.0.0.0:9000", "-P", "Working"]
重新构建并运行容器后,外部客户端即可正常连接WebSocket服务。
对于NATS服务的情况,需检查其WebSocket配置,确保监听地址为0.0.0.0而非127.0.0.1。
内容的提问来源于stack exchange,提问作者ronen
相关产品推荐
相关产品推荐

