Назначить статический IP для контейнера Docker

205

Я сейчас пытаюсь назначить статический IP 172.17.0.1 при запуске контейнера Docker.

Я использую порт 2122 в качестве порта ssh этого контейнера, чтобы позволить этому контейнеру прослушивать порт 2122.

sudo docker run -i -t -p 2122:2122 ubuntu

Эта команда запускает контейнер Docker со случайным IP-адресом, таким как 172.17.0.5, но мне нужно назначить конкретный IP-адрес для контейнера.

Следующий сценарий оболочки - это то, что я ссылаюсь на документацию Docker в расширенных сетевых настройках.

pid=$(sudo docker inspect -f '{{.State.Pid}}' <container_name> 2>/dev/null)
sudo rm -rf /var/run/netns/*
sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
sudo ip link add A type veth peer name B
sudo brctl addif docker0 A
sudo ip link set A up
sudo ip link set B netns $pid
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link delete eth0
sudo ip netns exec $pid ip link set dev B name eth0
sudo ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link set eth0 up
sudo ip netns exec $pid ip addr add 172.17.0.1/16 dev eth0
sudo ip netns exec $pid ip route add default via 172.17.42.1

Этот сценарий оболочки назначит статический IP 172.17.0.1 и установит связь со всем миром. Но всякий раз, когда я пытаюсь подключиться к этому контейнеру из моего локального хранилища, это не сработало. В чем проблема, возможно, я встретил?

LarryLo
источник
Боюсь, что нет простого ответа на этот вопрос, смотрите github.com/docker/docker/issues/6743 и github.com/docker/docker/issues/1179 , а также читайте github.com/jpetazzo/pipework
user2915097
@larrylo Можете ли вы подтвердить, что вы запустили sshd внутри контейнера?
Брайан,
5
Вы отменяете все маршруты, которые делает для вас демон Docker. Контейнеры не являются виртуальными машинами.
user2105103
Да, я подтверждаю, что могу запустить sshd внутри контейнера
LarryLo

Ответы:

291

Легко с 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/

cantSleepNow
источник
1
Отличный ответ - просто добавив немного дополнительной информации: blog.jessfraz.com/post/ips-for-all-the-things
Оле
@cantSleepNow по какой-то причине мне нужно просто использовать свой собственный созданный по умолчанию мост br0, который создается в файле интерфейсов во время загрузки системы (поэтому он НЕ создается с помощью создания сети в докере), не могли бы вы подсказать, как я могу получить тот же эффект - -ip параметр (получить фиксированный IP-адрес для контейнера) без создания моего моста с помощью Docker?
Мохаммед Нурельдин
@MohammedNoureldin Я не совсем понимаю - звучит как новый вопрос, я думаю, вы должны задать его как таковой.
cantSleepNow
@cantSleepNow Я имею в виду, что мне нужно исправить IP-адрес контейнера, хотя я НЕ использую настраиваемый мост (поэтому параметр --ip нельзя использовать), вы предлагаете какой-либо способ получить это?
Мохаммед Нурельдин
@MohammedNoureldin Я не уверен. Как я уже сказал, опубликуйте свой вопрос как вопрос, а не как комментарий - возможно, найдется кто-то, кто знает ответ.
cantSleepNow
89

Для docker-composeвы можете использовать следующиеdocker-compose.yml

version: '2'
services:
  nginx:
    image: nginx
    container_name: nginx-container
    networks:
      static-network:
        ipv4_address: 172.20.128.2
networks:
  static-network:
    ipam:
      config:
        - subnet: 172.20.0.0/16
          #docker-compose v3+ do not use ip_range
          ip_range: 172.28.5.0/24

с хоста вы можете протестировать используя:

docker-compose up -d
curl 172.20.128.2

Модерн docker-composeне меняет IP-адрес так часто.

Чтобы найти ips всех контейнеров docker-composeв одной строке, используйте:

for s in `docker-compose ps -q`; do echo ip of `docker inspect -f "{{.Name}}" $s` is `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $s`; done

Если вы хотите автоматизировать, вы можете использовать что-то вроде этого примера

zainengineer
источник
2
Похоже, это будет работать только в docker-compose v2, v3 нарушена совместимость.
Анджей Реманн
4
При использовании docker-compose v3 + removeip_range
Andrzej Rehmann
Я не получаю ip_range, хотя. разве это не покрыто подсетью? В любом случае, спасибо! Это исправило мое «Я должен снова посмотреть ip моего контейнера Монго» - выпуск
Бен,
1
Есть ли способ указать IP-адрес в композитной версии 3?
Ealeon
2
Решение прекрасно работает без меня ip_range. Я использую версию: «3.4».
Михаил Морфиков
24

Не прямой ответ, но это может помочь.

Я запускаю большинство моих dockerized сервисов, привязанных к собственным статическим ips, используя следующий подход:

  1. Я создаю IP-псевдонимы для всех служб на хосте докера
  2. Затем я запускаю каждый сервис, перенаправляющий порты из этого ip в контейнер, чтобы у каждого сервиса был свой статический ip, который мог бы использоваться внешними пользователями и другими контейнерами.

Образец:

docker run --name dns --restart=always -d -p 172.16.177.20:53:53/udp dns
docker run --name registry --restart=always -d -p 172.16.177.12:80:5000 registry
docker run --name cache --restart=always -d -p 172.16.177.13:80:3142 -v /data/cache:/var/cache/apt-cacher-ng cache
docker run --name mirror --restart=always -d -p 172.16.177.19:80:80 -v /data/mirror:/usr/share/nginx/html:ro mirror
...
ISanych
источник
Спасибо ~ Я знаю это. Так же, как и github.com/brandon-rhodes/fopnp/tree/m/playground . Я попробую.
LarryLo
1
Это очень хорошее решение, я просто прикрепил бы эту ссылку для новых пользователей, чтобы узнать о псевдонимах cyberciti.biz/faq/…
Мохаммед Нурельдин
Спасибо за хорошее решение.
RavinderSingh13
4

Это работает для меня.

Создать сеть с docker network create --subnet=172.17.0.0/16 selnet

Запустить образ докера docker run --net selnet --ip 172.18.0.2 hub

Сначала я получил

docker: Error response from daemon: Invalid address 172.17.0.2: It does not belong to any of this network's subnets.
ERRO[0000] error waiting for container: context canceled

Решение: Увеличена 2-я четверка IP [.18. вместо .17.]

Нильс Ценкер
источник
3
На этой странице в другом месте есть аналогичный / идентичный ответ на 2 года: stackoverflow.com/a/35359185/694469
KajMagnus
2

Я наткнулся на эту проблему во время попытки взломать Avahi, который должен знать свой публичный IP-адрес, чтобы нормально функционировать. Назначение статического IP-адреса контейнеру затруднительно из-за отсутствия поддержки статического назначения IP-адреса. в Docker.

В этой статье описывается методика назначения статического IP-адреса контейнеру в Debian :

  1. Сервис Docker должен быть запущен с DOCKER_OPTS="--bridge=br0 --ip-masq=false --iptables=false". Я предполагаю, что br0мост уже настроен.

  2. Контейнер должен быть запущен с --cap-add=NET_ADMIN --net=bridge

  3. Внутри контейнера pre-up ip addr flush dev eth0в /etc/network/interfacesможет быть использован , чтобы закрыть IP - адрес , назначенный Докер , как в следующем примере:


auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    pre-up ip addr flush dev eth0
    address 192.168.0.249
    netmask 255.255.255.0
    gateway 192.168.0.1
  1. Скрипт входа в контейнер должен начинаться с /etc/init.d/networking start. Также сценарий ввода должен отредактировать или заполнить /etc/hostsфайл, чтобы удалить ссылки на назначенный Docker IP.
Onlyjob
источник
2

Вы можете установить IP во время его запуска.

docker run --cap-add=NET_ADMIN -dit imagename /bin/sh -c "/sbin/ip addr add 172.17.0.12 dev eth0; bash"

Смотрите мой пример на https://github.com/RvdGijp/mariadb-10.1-galera

Как грубо
источник
к сожалению, это добавляет еще один IP-адрес, если IP-адрес был назначен в процессе ранее, это приводит к наличию двух IP-адресов
davey
1

Вы можете получить доступ к сервису других контейнеров по их имени ( ping apacheполучите ip или curl http://apacheполучите доступ к сервису http) И это может быть альтернативой статическому ip.

Гизонг Хе
источник
3
В докер версии 1.8 это работает напрямую. В более новой версии вы должны сначала связать эти контейнеры.
Guisong He
0

Если вы хотите, чтобы у вашего контейнера был собственный виртуальный Ethernet-сокет (с собственным MAC-адресом), iptables, используйте драйвер Macvlan. Это может быть необходимо для маршрутизации трафика на ваш маршрутизатор / ISP.

https://docs.docker.com/engine/userguide/networking/get-started-macvlan

FlappySocks
источник