docker-compose 连接来自 LAN 上不同设备的服务器/客户端容器

Posted

技术标签:

【中文标题】docker-compose 连接来自 LAN 上不同设备的服务器/客户端容器【英文标题】:docker-compose connect server/client containers from different devices on LAN 【发布时间】:2019-03-03 12:51:27 【问题描述】:

我正在使用 docker-compose 在本地网络的不同设备上部署服务器/客户端应用程序。我的设置如下:

在我的 docker-compose.yml 文件中,我有一个名为“server”的服务,它依赖于两个附加服务(“database”和“web”)。这三个服务在同一台设备上运行,并且能够相互成功连接。 “服务器”服务部署了基于 Flask 的 API,理想情况下,该 API 应该等待来自同一 LAN 中其他设备的请求。

在同一个 docker-compose.yml 文件中,我有一个名为“客户端”的服务,它运行一个应用程序,该应用程序应该部署在同一 LAN 中的多个设备上。独立于运行它的设备的“客户端”服务应该能够向位于同一 LAN 中的不同设备上的“服务器”服务发送请求。

这是我的 docker-compose.yml 文件:

version: '3.5'

networks:
  outside:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 192.168.220.0/24

services:

  client:
    build: ./client
    environment:
      TZ: "Europe/Madrid"
    command: >
      sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &&
      echo $TZ > /etc/timezone &&
      nmap -p 8080 192.168.220.220 &&
      python -u client/main_controller.py"
    restart: always
    volumes:
      - .:/code
    networks:
      outside:


  server:
    build: ./server
    environment:
      TZ: "Europe/Madrid"
    command: >
      sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &&
      echo $TZ > /etc/timezone &&
      python -u server/main_server.py"
    volumes:
      - .:/code
    ports:
      - "8080:8080" # host:container
    restart: always
    depends_on:
      - database
      - web
    networks:
      default:
      outside:
        ipv4_address: 192.168.220.220

  database:
    image: mysql:latest
    #command: ./database/run_db.sh #mysqld --user=root --verbose
    restart: always
    volumes:
      - ./database:/docker-entrypoint-initdb.d/:ro
    ports:
      - "3306:3306" # host:container
    environment:
      MYSQL_ROOT_PASSWORD: root
    networks:
      default:


  web:
    image: nginx:latest
    restart: always
    ports:
      - "8081:80"
    volumes:
      - ./interface:/www
      - ./interface/nginx.conf:/etc/nginx/conf.d/default.conf
    networks:
      default:

我正在使用 python 请求库使用以下 url 将请求从“客户端”发送到“服务器”:

http://192.168.220.220:8080

我的问题是,当我在同一设备 [deviceA] 上运行两个容器“客户端”和“服务”时,它们能够成功通信。

但是当我在不同的设备上运行容器时(使用 Mac OS X [deviceA] 的计算机上的“服务”和 Raspberry Pi [deviceB] 上的“客户端”,两者都使用 wi-fi 连接到同一个 LAN) ,“客户端”无法访问指定的 IP 和端口。

为了测试设备是否能够访问 IP:port 组合,我在运行“客户端”服务后立即使用以下命令:

nmap -p 8080 192.168.220.220

在 [deviceA] 上给出以下输出:

client_1    | Starting Nmap 7.01 ( https://nmap.org ) at 2019-03-03 12:22 Europe
client_1    | Nmap scan report for raspberry_escape_controller_server_1.raspberry_escape_controller_outside (192.168.220.220)
client_1    | Host is up (0.00012s latency).
client_1    | PORT     STATE SERVICE
client_1    | 8080/tcp open  http-proxy
client_1    | MAC Address: <mac_address> (Unknown)
client_1    |
client_1    | Nmap done: 1 IP address (1 host up) scanned in 0.71 seconds

以及 [deviceB] 上的以下一个:

client_1    | Starting Nmap 7.40 ( https://nmap.org ) at 2019-03-03 13:24 CET
client_1    | Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
client_1    | Nmap done: 1 IP address (0 hosts up) scanned in 0.78 seconds

----------- [编辑 1] -----------

正如 DTG 所建议的,这里是 [deviceB] 上 netstat 命令的输出:

root@a9923f852423:/code# netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.220.1   0.0.0.0         UG        0 0          0 eth0
192.168.220.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0

好像看不到[deviceA],应该是192.168.220.220

【问题讨论】:

检查 docs.docker.com/network/iptables/… 是否在 /etc/docker/daemon.json 中将 iptables 设置为 false 可能会产生类似的结果 我在两台机器上都把参数改成了false,但似乎没有做任何改变。 除非您想自己处理路由,否则不应将其设置为false 【参考方案1】:

在我看来,即使该服务已在您的 [deviceA] 中启动并运行,但有某种防火墙不允许从外部连接到它。

也许您需要检查 [deviceA] 上的防火墙配置。

路由问题

如果是路由问题,您应该在 hostB 中看到路由表

netstat -nr

并查看到 hostA 的有效路由存在

如果不存在有效的路线,您应该添加一条

sudo route add -net hostA_IP/MASK gw HOSTB_DEFAULT_GATEWAY

码头工人间通讯

创建网络后,您可以使用 docker run --network= 选项在其上启动容器。您在此网络中启动的容器必须驻留在同一 Docker 主机上。网络中的每个容器都可以立即与网络中的其他容器通信。

阅读有关了解 docker 通信的更多信息: See docker documentation here

【讨论】:

感谢您的评论。我检查了它的防火墙,但它看起来像是被禁用了。可以看截图here。 您可以从其他主机或网络中的某个点连接到您的 macbook 吗? 按照您的建议使用 telnet:从 [deviceA] 的“客户端”容器内部运行它能够到达主机:root@ccaba82bb26e:/code# telnet 192.168.220.220 8080 Trying 192.168.220.220 ... 连接到 192.168.220.220。尽管从 [deviceB] 上的“客户端”容器内部运行时,它无法建立连接:root@a9923f852423:/code# telnet 192.168.220.220 8080 Trying 192.168.220.220... telnet: Unable to connect to remote主机:没有路由到主机 啊,是问题(NO ROUTE T​​O HOST),表示deviceB不知道如何到达deviceA,是路由问题 您应该查看 hostB 中的路由表、IP 以及应该允许从 hostB 内部发起的传出连接的防火墙。您可以在 hostB 中使用:code netstat -nr ifconfig code 来检查您的网络状态

以上是关于docker-compose 连接来自 LAN 上不同设备的服务器/客户端容器的主要内容,如果未能解决你的问题,请参考以下文章

在docker-compose中连接tomcat和mysql

路由器上面的WAN口和LAN口是啥意思

WAN口与LAN口指啥,应该怎样连接?

路由器的那个wan口和lan口怎么连接

双 LAN 工作站上的默认 Internet 连接

docker springboot 仅通过 docker-compose 在 postgres 5432 上连接