你如何将 WebSocket 服务器 docker 化?

我在将我的 WebSocket 服务器放入 Docker 容器时遇到了问题。


这是服务器代码,它使用“connected”写入新连接。


// server.go

func 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.go

func 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.8

COPY . $GOPATH/src/websocket-test

WORKDIR $GOPATH/src/websocket-test

RUN ["go", "build", "server.go"]

EXPOSE 8000

CMD ["./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 连接到我的服务器。


PIPIONE
浏览 180回答 1
1回答

杨魅力

当您指定要侦听的主机名或 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&nbsp;iptables -t nat -n -L
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go