docker - 为什么只有 `expose` 配置的服务能够与互联网通信?

标签 docker networking docker-compose

关于 docker 网络的一些事情让我感到困惑。我有一个 docker-compose.yml可以像这样简化的文件:

version: '3.8'
services:
    foo:
        ...
        networks:
            - main_network
        ports:
            - "3000:3000"
    bar:
        ...
        networks:
            - main_network
        expose:
          - "5000"
networks:
    main_network:
根据 this answer , expose ...

Expose ports without publishing them to the host machine - they’ll only be accessible to linked services. Only the internal port can be specified.


如果这是真的,bar应该只将 5000 端口暴露给 foo服务。它似乎按预期工作。如果,我运行 bash进入 bar服务并执行:
$ ss -lntu 
5000端口正确打开:
Netid    State     Recv-Q  Send-Q   Local Address:Port    Peer Address:Port
...
tcp      LISTEN    0       128      0.0.0.0:5000          0.0.0.0:*
...
正如预期的那样,从我的容器外部,例如使用 Web 浏览器,我无法连接到该主机。另外,如果我跑
$ nmap -p1-65535 127.0.0.1
我可以验证 只有 foo 的 3000/TCP 端口服务开通:
PORT     STATE SERVICE
3000/tcp open  ppp
所以,我不明白的是IRL,我的bar服务能够连接到 Mongo Atlas 在线或 ping 互联网。如果端口没有暴露/打开以接收它,它如何得到它的答案?

最佳答案

您链接的答案既旧又不正确。

  • EXPOSE关键字主要是空操作。它提供信息(“此图像将在这些端口上提供服务”),但不会对操作产生任何影响。
    在旧版本的 Docker 中,EXPOSE关键字可用于链接容器的服务发现,但是 (a) 它仍然没有任何操作影响——无论是否有匹配的端口都可用 EXPOSE -- 并且容器“链接”已被弃用一段时间。
  • 默认情况下,容器具有出站 Internet 访问权限。出站访问通过主机防火墙中的简单 NAT 规则进行管理 nat表(以及 filter FORWARD 链中的相应规则)。例如,在我运行 Docker 20.10.2 的系统上,在 FORWARD 中我有链:
    -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    -A FORWARD -o docker0 -j DOCKER
    -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
    -A FORWARD -i docker0 -o docker0 -j ACCEPT
    
    第一条规则传递属于现有 TCP 连接一部分的数据包。这允许出站连接的返回数据包。
  • 关于docker - 为什么只有 `expose` 配置的服务能够与互联网通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65784039/

    相关文章:

    linux - ip_hdr 和 ipip_hdr 有什么区别?

    php - 使用 Docker 运行 Laravel artisan 命令时连接被拒绝

    docker - 如何将LinkedIn的Burrow添加到Docker Compose?

    docker - 使用localhost的Docker端口转发

    python - 从 python 启动 docker 容器弄乱了终端设置

    c - 非阻塞 DNS 解析

    networking - TCP 流与 UDP 消息

    linux - 难以访问 Docker 的 API

    docker - 从容器内查找容器的镜像 ID