从主机连接到 docker-compose 介导的 docker 内的 python 套接字

Connect to a python socket inside a docker-compose mediated docker from host

我正在尝试在 docker 中创建一个 python 套接字,并将该端口转发到它的主机,到其他一些程序应该尝试连接的地方。

为此,dockerised 运行 python 正在执行以下操作:

# Python 3.8, inside docker

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', 5000))
while True:
    message, addrs = s.recvfrom(1480)
    _log(f"DATA RECIEVED from {addrs}")  # arbitrary logging function

由于其他程序事先不知道将为 dockers 网络确定哪个 ip 范围,我必须信任 docker 的端口通信。所以,我想要实现的是,当主机收到任何在其 5000 端口上进行连接的套接字时,它将被 dockerised python.

选中

服务器和docker化图像都是ubuntus。主机在本地网络的ip是192.168.1.141,docker子网在172.18.0.0,docker-compose for docker本身如下:

docker-compose file

version: "3"

services:
  my_docker:
    container_name: python_socket
    image: registry.gitlab.com/my_group/my_project:latest
    volumes:
      - ./configs:/configs
      - ./logs:/configs/logs
      - ./sniffing:/app/sniffing
    ports:
      - "5000:5000"
      - "3788:3788"
      - "3787:80"
    networks:
      - app_network
    extra_hosts:
      - "host.docker.internal:host-gateway"
    depends_on:
      - rabbitmq
      - backend
    restart: always

networks:
  app_network:

使用此配置,我无法连接。我已经看到,在主机中,如果我启动 Ipython 并尝试以下操作:

# Python 3.8, ipython console
data = "Hello"

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('172.18.0.2', 5000))
s.send(data.encode())

然后此信息成功到达 docker。但是如果我尝试连接到 0.0.0.0:5000、localhost:5000 或 192.168.1.141:5000,那么我只会收到连接错误。 docker 也正在从机器外部获取信息。

我错过了什么?我在 docker 端口转发成功的地方配置了 web 服务器。

提前感谢您的宝贵时间和帮助。

您正在创建 UDP 套接字 (SOCK_DGRAM)。 Compose ports: is somewhat quiet on this feature, but the general Container networking 概述意味着端口转发默认为 TCP。

您可以明确指定您需要转发一个 UDP 端口:

ports:
  - '5000:5000/udp'

然后您可以连接到主机的 DNS 或 IP 地址(或 localhost 或 127.0.0.1,如果您从容器外部但在同一主机上调用)和第一个端口号 5000。不要查找容器私有 IP 地址;这是不必要的,在大多数情况下都不起作用。