Docker 应用服务器的 IP 地址 127.0.0.1 和 0.0.0.0 IP 的区别。

46
大家好。我正在使用Docker并尝试将一个简单的Django应用程序docker化,该应用程序对一个网页(真实网站)进行外部http连接。当我在Docker文件中设置了Django服务器的地址以在容器中工作时-127.0.0.1:8000,我的应用程序无法正常工作,因为无法对该网站进行外部连接。
但是,当我为我的服务器设置端口:0.0.0.0:8000时,它开始工作。 所以我的问题是:为什么会这样呢?在这种特殊情况下有什么区别?我只是想理解它。
我阅读了一些关于0.0.0.0的文章,它像是一种“通用”或“占位符”端口,允许使用OC默认端口。
127.0.0.1就像一个主机,将请求重定向到当前计算机。我知道这一点。 但是,当我在本地计算机上运行应用程序(主机:127.0.0.0:8000)时,一切都正常工作,应用程序可以连接到真实网站,但在Docker的情况下,它停止工作。
感谢任何帮助!
这是我的源代码: Docker文件
FROM python:3.6

RUN mkdir /code
WORKDIR /code

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . ./

EXPOSE 8000

ENTRYPOINT [ "python", "manage.py" ]
CMD [ "runserver", "127.0.0.1:8000" ] # doesn't work
# CMD [ "runserver", "0.0.0.0:8000" ] - works

docker-compose.yml

version: "3"
services:
  url_rest:
    container_name: url_keys_rest
    build:
      context: .
      dockerfile: Dockerfile
    image: url_keys_rest_image
    stdin_open: true
    tty: true
    volumes:
      - .:/var/www/url_keys
    ports:
      - "8000:8000"

以下是我在127.0.0.1的情况下收到的HTTP错误信息,或许对你有帮助。

http: error: ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8000): Max retries exceeded with url: /api/urls (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x10cd51e80>: Failed to establish a new connection: [Errno 61] Connection refused')) while doing GET request to URL: http://127.0.0.1:8000/api/urls
2个回答

59

如果您不将容器的主进程绑定到特殊的0.0.0.0“所有接口”地址,它就无法从容器外部访问。

在Docker中,127.0.0.1几乎总是指“此容器”,而不是“此计算机”。如果您从容器向127.0.0.1发起出站连接,则会返回到同一容器;如果您将服务器绑定到127.0.0.1,则它将不接受来自外部的连接。


Docker的核心之一是为每个容器提供独立的网络空间。特别地,每个容器都有自己的lo接口和自己的localhost概念。

在非常低层次上,网络服务调用bind(2)系统调用开始接受连接。这需要一个地址参数。它可以是两种情况之一:可以是某个系统接口的IP地址,也可以是特殊的0.0.0.0“所有接口”地址。如果您选择一个接口,则它只会接受该接口的连接;例如,如果物理系统上有两张网络卡,您可以使用它来仅接受来自其中一张网络但不是另一张的连接。

因此,如果将一个服务设置为绑定到 127.0.0.1,那么这就是 lo 接口的地址,并且该服务只会接受来自该接口的连接。但是每个容器都有自己的 lo 接口和自己的 localhost,所以这个设置会导致该服务拒绝除了容器内部发起的连接之外的所有连接。如果将其设置为绑定到 0.0.0.0,则还会接受来自容器内部的每个 eth0 接口的连接,所有从容器外部发起的连接都会通过该接口到达。


6
谢谢你的回答。说实话,我需要读几遍才能理解,因为这个解释太过“技术化”了。我的现有知识水平还不足以100%理解,但我至少理解了一些。谢谢。 - Velidan

6
我的理解是,Docker会为每个容器随机分配IP地址,而不是使用 localhost(127.*.*.*)。因此,在 Docker 应用程序内部使用 0.0.0.0 进行监听将起作用。我以前在 Docker 文件中尝试连接本地数据库时使用了 localhost,但并没有成功。我猜这是由于这个原因。如果我错了,请纠正我!更新:我附上了一个直观的图像,展示了 Docker 如何与这些 IP 地址交互。希望这能帮助理解。

enter image description here


如果您尝试通过 http://url_rest:8000 访问URL,您将获得API。就像Zhen404所说,Docker每次都会随机分配IP地址。 - Paulo Henrique
谢谢你,zhen。在某些情况下,我觉得你是正确的。 - Velidan

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