Как установить статический IP-адрес в контейнере Docker?
Я вполне доволен диапазоном IP, который докер предоставляет мне по умолчанию (176.17.xx), поэтому мне не нужно создавать новый мост, я просто хочу предоставить своим контейнерам статический адрес в этом диапазоне поэтому я могу напрямую указать на него клиентские браузеры.
Я попытался использовать
RUN echo "auto eth0" >> /etc/network/interfaces
RUN echo "iface eth0 inet static" >> /etc/network/interfaces
RUN echo "address 176.17.0.250" >> /etc/network/interfaces
RUN echo "netmask 255.255.0.0" >> /etc/network/interfaces
RUN ifdown eth0
RUN ifup eth0
из файла Docker, и он правильно заполнил файл интерфейсов, но сам интерфейс не изменился. Фактически, запуск ifup eth0 внутри контейнера получает эту ошибку:
RTNETLINK ответы: операция не разрешена
Не удалось вызвать eth0
Ответы
Ответ 1
Я уже ответил на это здесь
fooobar.com/questions/66399/...
но теперь я вижу, что этот вопрос на самом деле старше, чем предыдущий, поэтому я также скопирую ответ:
Простая версия Docker версии 1.10.1, постройте 9e83765.
Сначала вам нужно создать свою собственную докерную сеть (mynet123)
docker network create --subnet=172.18.0.0/16 mynet123
чем просто запустить изображение (я возьму ubuntu в качестве примера)
docker run --net mynet123 --ip 172.18.0.22 -it ubuntu bash
то в оболочке ubuntu
ip addr
Кроме того, вы можете использовать
--hostname
, чтобы указать имя хоста
--add-host
, чтобы добавить дополнительные записи в /etc/hosts
Документы (и почему вам нужно создать сеть) на https://docs.docker.com/engine/reference/commandline/network_create/
Ответ 2
Я использую метод, написанный здесь из официальной документации Docker, и я подтвердил, что он работает:
# At one shell, start a container and
# leave its shell idle and running
$ sudo docker run -i -t --rm --net=none base /bin/bash
[email protected]:/#
# At another shell, learn the container process ID
# and create its namespace entry in /var/run/netns/
# for the "ip netns" command we will be using below
$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f
2778
$ pid=2778
$ sudo mkdir -p /var/run/netns
$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
# Check the bridge IP address and netmask
$ ip addr show docker0
21: docker0: ...
inet 172.17.42.1/16 scope global docker0
...
# Create a pair of "peer" interfaces A and B,
# bind the A end to the bridge, and bring it up
$ sudo ip link add A type veth peer name B
$ sudo brctl addif docker0 A
$ sudo ip link set A up
# Place B inside the container network namespace,
# rename to eth0, and activate it with a free IP
$ sudo ip link set B netns $pid
$ sudo ip netns exec $pid ip link set dev B name eth0
$ sudo ip netns exec $pid ip link set eth0 up
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0
$ sudo ip netns exec $pid ip route add default via 172.17.42.1
Используя этот подход, я запускаю свои контейнеры всегда с net = none и устанавливаю IP-адреса с помощью внешнего script.
Ответ 3
На самом деле, несмотря на мой первоначальный сбой, ответ @MarkO'Connor был прав. Я создал новый интерфейс (docker0) в файле моего хоста /etc/network/interfaces, запустил sudo ifup docker0 на хосте, а затем запустил
docker run --net=host -i -t ...
который взял статический IP-адрес и назначил его docker0 в контейнере.
Спасибо!
Ответ 4
Контейнеры-докеры по умолчанию не имеют достаточных привилегий для управления сетевым стеком. Вы можете попробовать добавить -cap-add = NET_ADMIN в команду run, чтобы разрешить эту конкретную возможность. Или вы можете попробовать --privileged = true (предоставляет все права) для тестирования.
Другой вариант - использовать pipework с хоста.
Ответ 5
& с pipework (192.168.1.1
ниже default gateway):
pipework br0 container-name 192.168.1.10/[email protected]
Изменить: не начинаться с --net=none
: это закрывает порты контейнера.
Смотрите дальнейшие примечания
Ответ 6
Это сработало для меня:
docker run --cap-add=NET_ADMIN -d -it myimages/image1 /bin/sh -c "/sbin/ip addr add 172.17.0.8 dev eth0; bash"
Разъяснения:
-
--cap-add=NET_ADMIN
имеют права на администрирование сети (т.е. для команды /sbin/ip
)
-
myimages/image1
изображение для контейнера
-
/bin/sh -c "/sbin/ip addr add 172.17.0.8 dev eth0 ; bash"
Внутри контейнера запустите ip addr add 172.17.0.8 dev eth0
, чтобы добавить новый ip-адрес 172.17.0.8 в этот контейнер (предостережение: используйте бесплатный ip-адрес сейчас и в будущем). Затем запустите bash, просто чтобы контейнер не был автоматически остановлен.
Bonus
Моя целевая сцена: настройте распределенное приложение с контейнерами, играющими разные роли в dist-app. "Контейнер-проводник" может самостоятельно выполнять команды докеров (внутри), чтобы при необходимости запускать и останавливать контейнеры.
Каждый контейнер сконфигурирован для того, чтобы знать, где подключиться для доступа к определенной роли/контейнеру в dist-приложении (поэтому набор ip для каждой роли должен быть известен каждому партнеру).
Для этого:
изображение, созданное с помощью этого файла Dockerfile
FROM pin3da/docker-zeromq-node
MAINTAINER Foobar
# install docker software
RUN apt-get -yqq update && apt-get -yqq install docker.io
# export /var/run/docker.sock so we can connect it in the host
VOLUME /var/run/docker.sock
команда сборки изображения:
docker build --tag=myimages/conductor --file=Dockerfile .
команда запуска контейнера:
docker run -v /var/run/docker.sock:/var/run/docker.sock --name=conductor1 -d -it myimages/conductor bash
- Запуск контейнеров с разными ролями.
Сначала (не обязательно) добавьте записи в /etc/hosts
, чтобы найти партнеров по ip или имени (опция --add-host
)
Второй (очевидно, необходимый) присваивает ip запущенному контейнеру (используйте
/sbin/ip
в нем)
docker run --cap-add=NET_ADMIN --add-host worker1:172.17.0.8 --add-host worker2:172.17.0.9 --name=worker1 -h worker1.example.com -d -it myimages/image1 /bin/sh -c "/sbin/ip addr add 172.17.0.8 dev eth0; bash"
Ответ 7
Я понял, что на данном этапе вы не смотрите на создание сетей с несколькими узлами, но я считаю, что вам, скорее всего, понадобится это в ближайшее время. Weave позволит вам сначала определить несколько контейнерных сетей на одном хосте, а затем потенциально переместить некоторые контейнеры на другой хост без потери статического IP-адреса присвоили ему.
Ответ 8
pipework также отлично, но если вы можете использовать имя хоста, отличное от ip, тогда вы можете попробовать этот script
#!/bin/bash
# This function will list all ip of running containers
function listip {
for vm in `docker ps|tail -n +2|awk '{print $NF}'`;
do
ip=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $vm`;
echo "$ip $vm";
done
}
# This function will copy hosts file to all running container /etc/hosts
function updateip {
for vm in `docker ps|tail -n +2|awk '{print $NF}'`;
do
echo "copy hosts file to $vm";
docker exec -i $vm sh -c 'cat > /etc/hosts' < /tmp/hosts
done
}
listip > /tmp/hosts
updateip
Вам просто нужно запускать эту команду каждый раз, когда вы загружаете свои докерные лаборатории
Здесь вы можете найти мои скрипты с дополнительной функцией dockerip
Ответ 9
Я обнаружил, что --net = host не всегда может быть лучшим вариантом, так как это может позволить пользователям отключить хост из контейнера! В любом случае выясняется, что причина, по которой я не мог правильно сделать это изнутри, состояла в том, что конфигурация сети была предназначена для ограничения сеансов, начинающихся с аргумента --privileged = true.
Ответ 10
Для полноты: существует другой метод, предложенный на форумах Docker. (Редактировать: и упоминается попутно по ответу от Андрея Сердюк).
Добавить статический IP-адрес в хост-системе, а затем опубликовать порты для этого ip, например. docker run -p 192.0.2.1:80:80 -d mywebserver
.
Конечно, этот синтаксис не будет работать для IPv6, и в документации не упоминается, что...
Это звучит неправильно для меня: обычные групповые привязки (*: 80) на хосте теоретически конфликтуют с контейнером. На практике порт Docker имеет приоритет и не конфликтует, поскольку он реализован с использованием iptables. Но ваш публичный контейнерный IP-адрес будет по-прежнему отвечать на все не конфликтующие порты, например. SSH.
Ответ 11
Вы можете настроить SkyDns с помощью инструмента обнаружения сервисов - https://github.com/crosbymichael/skydock
Или: просто создайте сетевой интерфейс и опубликуйте в нем порты контейнера докеров, как здесь https://gist.github.com/andreyserdjuk/bd92b5beba2719054dfe