【问题标题】:Unable to Access Local Host From Docker Container无法从 Docker 容器访问本地主机
【发布时间】:2020-02-19 18:30:11
【问题描述】:

问题

我有两个 Docker 容器:

  • 一个服务器运行fastapi;uvicorn
  • 客户端向http://0.0.0.0发送GET请求

服务器似乎工作得很好,因为 bashing curl -X GET http://0.0.0.0 按预期工作。但是,我的 docker 客户端似乎无法访问。

构建客户端容器(以下文件)后,运行docker run -it --name app_client_container app_client:latest 时收到以下错误:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='0.0.0.0', port=80): Max retries exceeded with url: / (Caused by NewConnectionError(': 无法建立新连接: Errno 111 Connection refused' ))

设置

我的项目是这样的

|- client.Dockerfile
|- client.py
|- client_req.txt
|- server.Dockerfile
|- server.py
|- server_req.txt

客户

# client.Dockerfile
FROM python:3.8

WORKDIR /srv
WORKDIR /srv
ADD client_req.txt /srv/client_req.txt
RUN pip install -r client_req.txt

ADD . /srv
CMD python /srv/client.py

# client.py
import json
import requests
import traceback

try:
    response = requests.get('http://0.0.0.0', timeout=5)
    print(json.dumps(response.json(), indent=4))
except Exception as e:
    print('Connection could not be established :(')
    print('Here is more information:')
    traceback.print_exc()

# client_req.txt
requests

服务器

# server.Dockerfile
FROM python:3.8

WORKDIR /srv
ADD server_req.txt /srv/server_req.txt
RUN pip install -r server_req.txt

EXPOSE 80

ADD . /srv
CMD uvicorn server:app --host 0.0.0.0 --port 80 --reload

# server.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}

# server_req.txt
fastapi
uvicorn

【问题讨论】:

  • 当您有多个容器需要通信时,我强烈建议使用 Docker Compose 或类似工具。它使容器间的通信变得更加简单。
  • @Chris 我会调查一下
  • 0.0.0.0 是一个特殊的 IPv4 地址,意思是“无处不在”;通常只告诉服务器要监听哪些接口才有意义,而不是作为出站 HTTP 请求的目标。当您的客户拨打电话时,您希望它去哪里?
  • @DavidMaze 我只是关注this tutorial,我的想法是一旦我启动并运行它就切换到127.0.0.1

标签: python docker fastapi uvicorn


【解决方案1】:

尝试使用docker run ... --net=host ... 运行客户端

虽然服务器将:80暴露给宿主机,但是宿主机的网络默认情况下对其他容器是不可用的;即主机的:80 在其他(包括客户端)容器中不可用。

或者,您可以:

  • 通过容器内的 DNS 引用主机;
  • 创建一个 docker 网络并将两个容器绑定到它(因此也使用容器名称来引用)
  • 或者 - 与之前的版本差不多 - 使用 Docker Compose。

【讨论】:

  • 谢谢,--net=host 标志解决了它。不过,我仍然会研究替代方案。
【解决方案2】:

你也可以使用default docker bridge network.

将IP地址设置为:172.17.0.1(对于mac是docker.for.mac.host.internal)
这应该有效:

response = requests.get('http://172.17.0.1', timeout=5)

【讨论】:

  • 我工作但我不明白为什么我不能使用say requests.get('http://localhost:4001/auth')
  • 让我们有两个正在运行的容器 c1 和 c2。如果您在 c1 内部,则调用 GET HTTP://localhost:4001 将指向自身,即容器 c1。 c1 只能使用桥接网络与外部世界(您的系统和 c2)进行通信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 2014-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
相关资源
最近更新 更多