为了账号安全,请及时绑定邮箱和手机立即绑定

你如何将 WebSocket 服务器 docker 化?

你如何将 WebSocket 服务器 docker 化?

Go
PIPIONE 2023-06-01 14:12:17
我在将我的 WebSocket 服务器放入 Docker 容器时遇到了问题。这是服务器代码,它使用“connected”写入新连接。// server.gofunc RootHandler(w http.ResponseWriter, r *http.Request) {    upgrader := websocket.Upgrader{ // (Uses gorilla/websocket)        ReadBufferSize:  4096,        WriteBufferSize: 4096,    }    conn, err := upgrader.Upgrade(w, r, nil)    if err != nil {        panic(err)    }    if err = conn.WriteMessage(websocket.TextMessage, []byte("connected")); err != nil {        panic(err)    }}func main() {    fmt.Println("server is running")    // For graceful shutdown    stop := make(chan os.Signal, 1)    signal.Notify(stop, os.Interrupt)    server := http.Server{Addr: "localhost:8000"}    defer server.Close()    http.HandleFunc("/", RootHandler)    go func() {        err := server.ListenAndServe()        if err != nil && err != http.ErrServerClosed {            panic(err)        }    }()    <-stop}这是客户端:// client.gofunc main() {    connection, _, err := websocket.DefaultDialer.Dial("ws://localhost:8000", nil)    if err != nil {        panic(err)    }    _, b, err := connection.ReadMessage()    if err != nil {        panic(err)    }    fmt.Println(string(b)) // "connected"}运行server.go然后client.go打印“已连接”,表明代码正在运行。现在我想把服务器放在一个 Docker 容器中。这是dockerfile:FROM golang:1.11.4-alpine3.8COPY . $GOPATH/src/websocket-testWORKDIR $GOPATH/src/websocket-testRUN ["go", "build", "server.go"]EXPOSE 8000CMD ["./server"]我使用这些命令来构建和启动容器,暴露 8000/tcp。docker build -t websocket-test .docker run -p 8000:8000 websocket-test我可以确认服务器正在运行,因为它打印“服务器正在运行”。如果我client.go从容器外开始,它会恐慌:panic: read tcp [::1]:60328->[::1]:8000: read: connection reset by peer我期望的是与以前相同的结果——在客户端打印“connected”。错误消息意味着服务器在握手之前断开了连接。我不明白“60328”这个数字。据我所知,WebSocket 不会在升级时更改端口,所以我应该可以只公开 8000。我不知道我必须更改什么才能通过 WebSocket 连接到我的服务器。
查看完整描述

1 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

当您指定要侦听的主机名或 IP 地址(在本例中localhost解析为127.0.0.1)时,您的服务器将仅侦听该 IP 地址。


当您在 Docker 容器之外时,监听localhost不是问题。如果您的服务器只监听127.0.0.1:8000,那么您的客户端可以轻松连接到它,因为连接也是从127.0.0.1.


当你在 Docker 容器中运行你的服务器时,它只会像以前一样监听127.0.0.1:8000。这127.0.0.1是一个本地环回地址,在容器外无法访问。


当您使用 启动 docker 容器时-p 8000:8000,它会将前往的流量转发127.0.0.1:8000到容器的 IP 地址,在我的例子中是172.17.0.2.


容器在 docker0 网络接口中获取 IP 地址(您可以使用命令查看ip addr ls)


因此,当您的流量被转发到 上的容器时172.17.0.2:8000,那里没有任何监听并且连接尝试失败。


修复:

问题出在监听地址上:


server := http.Server{Addr: "localhost:8000"}

要解决您的问题,请将其更改为


server := http.Server{Addr: ":8000"}

这将使您的服务器监听所有容器的 IP 地址。


附加信息:

当您在 Docker 容器中公开端口时,Docker 将创建 iptables 规则来执行实际的转发。看到这个。您可以使用以下方式查看这些规则:


iptables -n -L 

iptables -t nat -n -L


查看完整回答
反对 回复 2023-06-01
  • 1 回答
  • 0 关注
  • 179 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信