#docker #docker-compose #nmap #port-scanning
Вопрос:
Я развертываю приложение в контейнере Docker. Приложение отправляет запросы на другой сервер с URL-адресом обратного вызова. URL-адрес обратного вызова содержит имя хоста и порта, на котором на самом деле работает приложение.
Настроить этот URL-адрес обратного вызова в «стабильной, нединамичной» тестовой среде легко, потому что мы знаем IP-адрес и порт, на котором работает приложение. Но в Docker URL обратного вызова-это IP-адрес хост-машины порт, который был настроен в файле docker-compose.yml. Таким образом, оба параметра являются динамическими и не могут быть жестко закодированы в изображении Docker.
Мне нужен IP-адрес хоста docker и открытый порт с информацией о контейнере каким-то образом в контейнере.
Вот как мой контейнер получает IP-адрес хост-машины docker:
version: '3'
services:
my-server:
image: ...
container_name: my-server
hostname: my-server
ports:
- "1234:9876"
environment:
- DOCKER_HOST_IP=${HOST_IP}
Я устанавливаю IP-адрес хоста при запуске контейнера:
HOST_IP=$(hostname -i) docker-compose up
Может быть, это не элегантный способ, но это лучшее, что я мог сделать до сих пор.
Но я понятия не имею, как получить информацию о открытом порту внутри контейнера. Моя идея заключалась в том, что, как только я узнаю IP-адрес хоста в контейнере, я смогу nmap $HOST_IP
каким-то образом получить список открытых портов и grep для соответствующей строки. Но это не работает, потому что я запускаю много контейнеров Docker на этом хосте, и я не могу выбрать правильную строку с помощью grep.
вот результат th nmap:
PORT STATE SERVICE
22/tcp open ssh
111/tcp open rpcbind
443/tcp open https
5001/tcp open commplex-link
5002/tcp open rfe
7201/tcp open dlip
1234/tcp open vcom-tunnel
1235/tcp open vcom-tunnel
1236/tcp open teradataordbms
60443/tcp open unknown
Поэтому, когда я выполняю nmap
из контейнера, я могу видеть все открытые порты на моей хост-машине. Но я понятия не имею, как выбрать строку, которая принадлежит контейнеру, в котором я нахожусь.
Могу ли я как-то настроить имя службы до того, как docker развернет контейнеры?
Каков наилучший способ получить номер порта, который был открыт контейнером на главной машине?
Ответ №1:
Вы должны передать полный URL-адрес обратного вызова, видимый извне, приложению.
ports:
- "1234:9876"
environment:
- CALLBACK_URL=http://physical-host.example.com:1234/path
Вы можете представить себе интересное разнообразие сценариев, в которых IP-адрес хоста также не может быть напрямую маршрутизирован. В качестве основного примера предположим, что вы запускаете контейнер на своем ноутбуке дома. IP-адрес ноутбука может быть 192.168.1.2/24, но это все равно «частный» адрес; вам нужен IP-адрес вашего маршрутизатора, видимый извне, и нет простого способа узнать это.
xx.xx.xx.xx /-------- 192.168.1.1 192.168.1.2 /----------------
------------| Router |---------------------------| Laptop |
--------/ | Docker |
| 172.17.1.2 |
Callback address must be | Server |
http://xx.xx.xx.xx/path ----------------/
В облачной среде вы можете представить аналогичную настройку с использованием балансировщиков нагрузки. Ваш контейнер может работать на каком-либо облачном экземпляре. Контейнер может прослушивать порт 11111, и вы переназначаете его на порт 22222 в экземпляре. Но перед этим у вас есть балансировщик нагрузки, который прослушивает обычный HTTPS-порт 443, завершает TLS, а затем перенаправляет на экземпляр , и у вас есть DNS-имя, подключенное к этому балансировщику нагрузки; адрес обратного вызова был бы https://service.example.com/path
, но без явного указания этого контейнеру, он никак не может это понять.