无法连接到 Docker 容器中的 Go Server

Can't connect to Go Server in Docker container

我正在尝试 运行 一个在 docker 容器内用 Golang 编写的 HTTP 服务器,但我一直收到连接被拒绝的请求。一切都在运行 Ubuntu 20.04 Server VM 运行ning 在我的 Windows 10 机器上。

Go 服务器代码:

package main

import "github.com/lkelly93/scheduler/internal/server"

func main() {
    server := server.NewHTTPServer()
    server.Start(3000)
}
package server

import (
    "context"
    "fmt"
    "net/http"
)

type HTTPServer interface {
    Start(port int) error

    Stop() error
}

func NewHTTPServer() HTTPServer {
    return &httpServer{}
}

type httpServer struct {
    server *http.Server
}

func (server *httpServer) Start(port int) error {
    serveMux := newServeMux()
    server.server = &http.Server {
        Addr: fmt.Sprintf(":%d", port),
        Handler: serveMux,
    }
    return server.server.ListenAndServe()
}

func (server *httpServer) Stop() error {
    return server.server.Shutdown(context.Background())
}

我的 Dockerfile:

FROM ubuntu:20.04

RUN apt-get update -y

#Install needed packages
RUN apt-get install software-properties-common -y
RUN apt-get install python3 -y
RUN apt-get update -y 
RUN apt-get install python3-pip -y
RUN apt-get install default-jre -y

#Install language dependacies
    #Python
    RUN pip3 install numpy

#Reduce VM size
# RUN rm -rf /var/lib/apt/lists/*

#Setup working DIRs
RUN mkdir secure
RUN mkdir secure/runner_files

COPY scheduler /secure
WORKDIR /secure

EXPOSE 3000

CMD ["./scheduler"] <-- The go server is compiled into a binary called scheduler

我构建给定的 Dockerfile 然后 运行:

docker run -d --name scheduler -p 3000:3000 scheduler:latest

然后我获取容器的地址:

docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' scheduler
->172.17.0.2

最后我使用 cURL 发送了一个 http 请求:

curl http://172.17.0.2:3000/execute/python --data '{"Code":"print(\"Hello\")"}'

我得到

curl: (7) Failed to connect to 172.17.0.2 port 3000: Connection refused

但应该得到

{"Stdout":"Hello\n"}%

如果我 运行 Ubuntu VM 上的 Go 服务器,我可以从我的 Win10 机器上调用它没有问题,但是当 Go 服务器存在于一个docker 来自 Ubuntu 机器的容器。

Go 代码比那个更复杂,但是 post 这里的所有内容都太多了,请随时在 https://github.com/lkelly93/scheduler.

查看整个 repo

最终它将成为我想要制作 运行 代码的网站的后端。像 LeetCode 或 Repl.it.

这样的东西

谢谢!

编辑:

docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
2a56a973040f        scheduler:latest    "./scheduler"       37 seconds ago      Up 36 seconds       0.0.0.0:3000->3000/tcp   scheduler

docker 容器日志 2a56a973040f 没有输出。

编辑 2:

docker run -it --net container:2a56a973040f nicolaka/netshoot ss -lnt
State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0      4096               *:3000            *:*

编辑 3:

阅读手册页后,我发现如果我的图像有标签 --network=host 然后 运行。

curl http://localhost:3000/execute/python --data '{"Code":"print(\"Hello\")"}'

我得到了正确的输出。虽然这可行,但我希望并排放置多个 docker 图像 运行ning。所以我更愿意使用 IP 地址来解决所有这些问题。所以我认为这不是永久性的修复。

您已发布端口,它将端口从 docker 主机转发到容器。因此你想连接到 http://localhost:3000。由于 docker 在 VM 内部运行,并且这些私有 IP 仅在 VM 中可见,因此在桌面安装中连接到容器 IP 可能会失败。

如果您碰巧是 运行 docker-machine(旧的 docker 工具箱安装就是这种情况),那么您需要获取 VM 的 IP。 运行echo $DOCKER_HOST查看IP地址,调整端口为3000端口

在进行了更多谷歌搜索后,我按照 this 指南创建了自己的“user-defined 桥接网络”。

如果我启动我的容器并将它连接到这个网络,那么它就可以工作了!如果有人能解释原因,我会很高兴!

为了在我的服务器上解决这个问题,我将 IP 地址设置为 0.0.0.0:4000。 我正在使用杜松子酒所以这个例子看起来像:

r := gin.Default()
r.run("0.0.0.0:4000")

在这之后我终于可以通过我的浏览器访问它了。