docker-компоновать серверные / клиентские контейнеры с разных устройств в локальной сети

#docker #flask #raspberry-pi #docker-compose

#docker #flask #raspberry-pi #docker-compose

Вопрос:

Я использую docker-compose для развертывания серверного / клиентского приложения на разных устройствах в моей локальной сети. Мои настройки следующие:

  • В моем файле docker-compose.yml у меня есть служба под названием ‘server’, которая зависит от двух дополнительных служб (‘database’ и ‘web’). Эти три службы запущены на одном устройстве и способны успешно подключаться друг к другу. Служба «сервер» развертывает API на основе Flask, который в идеале должен ожидать запросов от других устройств в той же локальной сети.

  • В том же самом файле docker-compose.yml у меня есть служба под названием «клиент», которая запускает приложение, которое должно быть развернуто более чем на одном устройстве в одной локальной сети. Служба «клиент», независимо от устройства, на котором она запущена, должна иметь возможность отправлять запросы службе «сервер», которая находится на другом устройстве в той же локальной сети.

Вот мой файл 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 amp;amp;
      echo $TZ > /etc/timezone amp;amp;
      nmap -p 8080 192.168.220.220 amp;amp;
      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 amp;amp;
      echo $TZ > /etc/timezone amp;amp;
      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
  

Моя проблема в том, что когда я запускаю оба контейнера, ‘client’ и ‘service’, на одном устройстве [DeviceA], они могут успешно взаимодействовать.

Но когда я запускаю контейнеры на разных устройствах («сервис» на компьютере с Mac OS X [DeviceA] и «клиент» на Raspberry Pi [DeviceB], оба подключены к одной локальной сети с помощью Wi-Fi), «клиент» не может достичь указанного 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, вот вывод команды netstat на [DeviceB]:

 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

Комментарии:

1. проверьте docs.docker.com/network/iptables /… как iptables установленное значение false в /etc/docker/daemon. json может дать аналогичные результаты

2. Я изменил параметр на false на обеих машинах, но, похоже, никаких изменений не вносит.

3. Не следует устанавливать значение false , если вы не хотите обрабатывать маршрутизацию самостоятельно.

Ответ №1:

Мне кажется, что, хотя служба запущена на вашем [DeviceA], существует какой-то брандмауэр, не разрешающий внешние подключения к ней извне .

Возможно, вам следует проверить конфигурацию брандмауэра на [DeviceA].

ПРОБЛЕМЫ С МАРШРУТИЗАЦИЕЙ

Если это проблема с маршрутизацией, вы должны увидеть таблицу маршрутизации в hostB с

 netstat -nr
  

И видит, что существует допустимый маршрут к hostA

Если не существует допустимого маршрута, вы должны добавить его с

 sudo route add -net hostA_IP/MASK gw HOSTB_DEFAULT_GATEWAY
  

КОММУНИКАЦИИ Между ДОКЕРАМИ

После создания сети вы можете запускать в ней контейнеры, используя опцию docker run —network=. Контейнеры, которые вы запускаете в этой сети, должны находиться на одном хосте Docker. Каждый контейнер в сети может немедленно взаимодействовать с другими контейнерами в сети.

Подробнее о понимании взаимодействия docker: смотрите документацию docker здесь

Комментарии:

1. Спасибо за ваш комментарий. Я проверил его брандмауэр, но, похоже, он отключен. Вы можете увидеть скриншот здесь .

2. И можете ли вы подключиться к своему macbook с другого хоста или точки в вашей сети?

3. Используя telnet, как вы предложили: запускаясь изнутри «клиентского» контейнера [DeviceA], он может достичь хоста: root@ccaba82bb26e:/code # telnet 192.168.220.220 8080 Пытается 192.168.220.220… Подключен к 192.168.220.220. Хотя при запуске из контейнера «клиент» на [DeviceB] он не может установить соединение: root@a9923f852423:/code # telnet 192.168.220.220 8080 Пытается 192.168.220.220… telnet: не удается подключиться к удаленному хосту: нет маршрута к хосту

4. Ах, вот в чем проблема (НЕТ МАРШРУТА К ХОСТУ), это означает, что DeviceB не знает, как связаться с DeviceA, это проблема маршрутизации

5. Вам следует посмотреть таблицу маршрутизации в hostB, IP-адрес, а также, вероятно, брандмауэр, который должен разрешать исходящие соединения, инициируемые изнутри hostB . Вы можете использовать: code netstat -nr ifconfig code в hostB для проверки состояния вашей сетевой работы