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

问题描述

我试图在Docker容器中运行一个用Golang编写的HTTP Server,但我一直拒绝连接。一切都在运行于Windows 10计算机上的Ubuntu 20.04 Server VM内部运行。

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机器上调用它没有问题,但是当ubuntu服务器中的Docker容器中存在Go服务器时,我似乎无法调用它。

Go代码要复杂得多,但要在此处发布所有内容实在太多了,您可以随时查看https://github.com/lkelly93/scheduler上的整个仓库。

最终,它将是我要使其运行代码的网站的后端。类似于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镜像并排运行。因此,我宁愿使用IP地址来解决所有问题。因此,我认为这不是永久性的解决方法

解决方法

您已经发布了端口,该端口将端口从Docker主机转发到容器。因此,您要连接到http:// localhost:3000。在台式机安装中,连接到容器IP可能会失败,因为docker在VM内部运行,而这些私有IP仅在VM中可见。

如果您碰巧正在运行docker-machine(在较旧的docker工具箱中就是这种情况),则需要获取VM的IP。运行echo $DOCKER_HOST以查看IP地址,并将端口调整为端口3000。

,

在执行更多谷歌搜索之后,我遵循了this指南,并创建了自己的“用户定义的桥接网络”。

如果我启动容器并将其附加到该网络,那么它将起作用!如果有人可以解释为什么我会喜欢的!