Skip to main content
 首页 » 编程设计

python之端口未公开但仍可在内部 docker 网络上访问

2025年05月04日29zhenyulu

(我遇到了暴露端口的逆问题,但它无法访问。)

在我的例子中,我在同一个网络上有 2 个容器。一个是运行 Python Flask 应用程序的 Alpine Python。另一个是准系统 Ubuntu 18.04。这些服务基本上是这样初始化的:

docker-compose.yml:

version: '3' 
 
services: 
  pythonflask: 
    build: someDockerfile # from python:3.6-alpine 
    restart: unless-stopped 
 
  ubuntucontainer: 
    build: someOtherDockerfile #from ubuntu:18.04 
    depends_on: 
      - pythonflask 
    restart: unless-stopped 

Python Flask 应用在端口 5000 上运行。 请注意 docker-compose.yml 文件中缺少 expose: - 5000。 问题是我在 cURLing http://pythonflask:5000 时能够得到正确的响应来自 ubuntucontainer

步骤:

$ docker exec -it ubuntucontainer /bin/bash 

...然后在容器中...

root@ubuntucontainer:/# curl http://pythonflask:5000/ 

...从 Flask 应用程序正确返回我的响应。

但是从我运行 docker 的机器上:

$ curl http://localhost:5000/ 

不返回任何内容(如预期)。

当我测试不同的端口时,它们每次都会自动暴露。这是做什么的?

请您参考如下方法:

容器之间的连接是通过将容器放在同一个 docker 网络上并通过容器 ip 和端口(而不是主机发布的端口)进行通信来实现的。那么 expose 有什么作用呢?

Expose 是文档

图像创建者使用 Expose in docker 来记录应用程序将在容器内监听的预期端口。除了使用此元数据文档的一些工具和 docker 中的标志外,它不用于控制容器之间的访问或修改 docker 的网络。应用程序可能会在运行时重新配置以监听不同的端口,并且您可以连接到尚未公开的端口。

对于容器之间的 DNS 查找,网络需要由用户创建,而不是来自 docker 的默认网络之一(例如,在名为“bridge”的默认桥接网络中未启用 DNS)。使用 DNS,您可以查找容器名称、服务名称(来自组合文件)以及在该网络上为该容器创建的任何网络别名。

等式的另一半是在 docker 中“发布”。这将创建从主机到容器的映射以允许外部访问。它是通过在主机上运行并转发新连接的代理进程实现的。由于实现,即使容器未监听端口,您也可以在主机上发布端口,尽管在这种情况下尝试连接到该端口时会收到错误消息。