Docker не имеет возможности сопоставить порт после создания контейнера или изменить существующее сопоставление портов.
Обычное решение - настроить приложение для использования заданного порта или диапазона портов. Если это невозможно, есть несколько вариантов решения проблемы.
Хост-сеть
Используйте docker run --network=host
. Контейнеры совместно используют сетевой стек хостов, поэтому они доступны по IP-адресу хостов. Обратите внимание, что это дает контейнеру доступ к сети хостов, поэтому он может мешать работе хост-служб или подвергать контейнер большей части вашего хоста, чем обычно.
Маршрутизируемая, определяемая пользователем сеть.
Создайте определяемую пользователем сеть для ваших контейнеров и назначьте ей диапазон IP-адресов, который сеть может маршрутизировать на хост Docker. Тогда службы, прослушивающие порты в контейнерах, становятся адресуемыми напрямую.
docker network create \
--subnet=10.1.3.0/24 \
-o com.docker.network.bridge.enable_ip_masquerade=false \
routable
Маршрут для новой сети докеров необходимо будет добавить к вашим сетевым шлюзам, чтобы они могли направлять трафик через ваш хост Docker. В Linux это будет примерно так:
ip route add 10.1.3.0/24 via $DOCKER_HOST_IP
Тогда вы сможете передавать данные как обычно
docker run --net=routable --rm -it alpine ping $DOCKER_HOST_GATEWAY_IP
Мост Маквлан
Docker имеет сеть macvlan. драйвер, который позволяет отображать интерфейс хоста в контейнер, что-то вроде мостового интерфейса в виртуальной машине. В этом случае контейнер может иметь интерфейс в той же сети, что и хост.
docker network create -d macvlan \
--subnet=10.1.2.0/24 \
-o macvlan_mode=bridge \
-o parent=enp3s0 macvlan
docker run --net=macvlan --ip=10.1.2.128 --rm -it alpine ping 10.1.2.1
Обратите внимание, что вы не можете связываться с IP-адресом хостов докеров через этот мост. Вы можете добавить к хосту субинтерфейс macvlan и переместить на него IP-адрес хоста, чтобы разрешить трафик.
Некоторым виртуальным машинам и виртуальным сетям при генерации данных не хватает дополнительных MAC-адресов, о которых они не знают. AWS EC2, например, отклонит трафик контейнеров.
Контейнер iptables
Можно создавать правила NAT iptables в пространстве имен контейнеров. Чтобы сделать это внутри контейнера, контейнеру нужна возможность NET_ADMIN
. Сценарий в какой-то форме может искать порты приложений после запуска и пересылать трафик с правилом DNAT
из ваших статических портов с внешним отображением на динамические порты приложений.
docker run -p 5000:5000 --cap-add=NET_ADMIN debian:9
# port=$(ss -lntpH | awk '/"app-bin"/ { split($4,a,":"); print a[length(a)]; exit}')
# iptables -t nat -A -p tcp -m tcp --dport 5000 -j DNAT --to-destination 127.0.0.1:$port
Вы можете аналогичным образом добавить iptables
правила с узла докеров для сетевого пространства имен контейнеров, если не хотите добавлять возможность NET_ADMIN
к контейнеру. Хосту требуется небольшая помощь для использования пространств имен контейнеров
pid=$(docker inspect -f '{{.State.Pid}}' ${container_id})
mkdir -p /var/run/netns/
ln -sfT /proc/$pid/ns/net /var/run/netns/$container_id
ip netns exec "${container_id}" iptables -t nat -vnL
person
Matt
schedule
13.12.2017