#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 ifconfigcode
в hostB для проверки состояния вашей сетевой работы