连接被拒绝:dial tcp 127.0.0.1:8000: connect: connection refused,涉及到golang、docker容器技术。

4

我正在尝试从一个使用GO语言的项目向另一个项目发起HTTP请求。发起请求的项目包含以下dockerfile:

FROM golang:alpine as builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main .
FROM scratch
WORKDIR /app
COPY --from=builder /build .
CMD ["./main"]

该等待请求的项目正在本地主机的8000端口运行,并具有以下dockerfile:
FROM golang:1.13.8 AS build-env
ADD . /dockerdev
WORKDIR /dockerdev
RUN go get -d -v ./...
RUN go build -o /server
# Final stage
FROM debian:buster
EXPOSE 8000
WORKDIR /
COPY --from=build-env /server /
CMD ["/server"]

当我编写

resp, err := http.Post("http://localhost:8000/orders", "application/json", bytes.NewBuffer(requestBody))

我遇到了以下错误:

拨号tcp 127.0.0.1:8000:连接被拒绝

由于我刚接触docker,所以欢迎提供改进意见!


在第二个Docker容器中,127.0.0.1本地主机名只会指向容器本身,而不是主机本身。去掉主机名,只列出端口号,即:8000,并确保端口号传递到主机操作系统。 - colm.anseo
对不起,我不明白... - fbarril
Docker容器具有独立的网络堆栈。在所有意义上,您可以认为它们在这方面是不同的计算机。因此,一个容器中的localhost与另一个容器中的localhost是不同的网络接口。请参阅https://docs.docker.com/network/network-tutorial-standalone/。 - Peter
你可以创建自己的网络并连接这两个容器,或者使用 --link 选项。使用 docker inspect <name-of-container> 命令检查配置,并检查网络。它们应该具有相同的网关。 - user6516856
docker-compose是一项有用的技术,可编排多个Docker容器并链接它们的网络。 - colm.anseo
2个回答

7

扩展我的评论。您的客户端代码的网络地址将无法使用:

resp, err := http.Post("http://localhost:8000/orders", "application/json", bytes.NewBuffer(requestBody)) // broken

因为它实际上在自己与自己交流(localhost 指代的是 客户端 docker容器 - 而不是宿主机操作系统)。


为了测试目的,将这两个容器暴露给您的宿主机操作系统最快的方法如下:

docker run -it --rm -p 8000:8000 dockweb  # server container
docker run -it --rm --net host dockcli    # client container

除了一些简单的测试外,这可能很快变得难以处理。因此我建议使用像docker-compose这样的工具,它可以方便地链接容器和它们的网络。

2020/09/13 18:24:47 发布 "http://:8000/orders": 拨号TCP :8000: 连接被拒绝 - fbarril
@fbarril更新了答案,并提出了一些短期和长期的建议。 - colm.anseo
如果有一个没有在容器中运行的东西(比如本地运行的 .Net Kestrel Web 服务器),你会怎么做呢?这很奇怪,因为我曾经有一些没有在容器中运行的东西可以自由地与 Redis、Elastic 等进行通信。 - Jeff Putz

0

尝试使用0.0.0.0代替localhost。这应该可以解决连接被拒绝的错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接