Перезапуск именованного контейнера назначает другой IP-адрес

Я пытаюсь развернуть свое приложение с помощью Docker и столкнулся с проблемой, заключающейся в том, что перезапуск именованных контейнеров назначает контейнеру другой IP-адрес. Возможно, объяснение того, что я делаю, лучше объяснит проблему:

  • Postgres запускается внутри отдельного контейнера с именем "postgres"
    $ PG_ID=$(docker run --name postgres postgres/image)
  • Контейнер моего веб-приложения связан с контейнером postgres
    $ APP_ID=$(docker run --link postgres:postgres webapp/image)

Связывание образа контейнера postgres с контейнером webapp вставляет в контейнер webapp запись файла hosts с IP-адресом контейнера postgres. Это позволяет мне указывать на базу данных postgres в моем веб-приложении, используя postgres:5432 (кстати, я использую Django). Все это работает хорошо, за исключением случаев, когда по какой-то причине происходит сбой postgres.

Прежде чем я вручную остановлю процесс postgres, чтобы имитировать сбой процесса postgres, я проверяю IP-адрес контейнера postgres:

$ docker inspect --format "{{.NetworkSettings.IPAddress}}" $PG_ID
172.17.0.73

Теперь, чтобы имитировать сбой, я останавливаю контейнер postgres:

$ docker stop $PG_ID

Если сейчас я перезапущу postgres, используя

$ docker start $PG_ID

IP контейнера меняется:

$ docker inspect --format "{{.NetworkSettings.IPAddress}}" $PG_ID
172.17.0.74

Поэтому IP-адрес, который указывает на контейнер postgres в контейнере веб-приложения, больше не является правильным. Я думаю, что, называя контейнер, Docker присваивает ему имя с определенными конфигурациями, чтобы вы могли надежно связываться между контейнерами (как сетью, так и томами). Если IP изменится, это, кажется, не поможет.

Если мне приходится перезапускать процесс моего веб-приложения каждый раз, когда я перезапускаю postgres, это не кажется лучше, чем просто использовать один контейнер для запуска обоих процессов. Затем я могу использовать супервизор или что-то подобное, чтобы они оба работали, и использовать localhost для связи между процессами.

Я все еще новичок в Docker, так что я делаю что-то не так или это ошибка в докере?


person miki725    schedule 13.07.2014    source источник
comment
Вы можете найти этот вопрос, связанный с & ответ полезен.   -  person Ben Whaley    schedule 14.07.2014
comment
Благодарю. посмотрю на ddns. надеюсь не будет так сложно. Docker кажется очень крутым, но, похоже, ему нужно немного научиться, чтобы правильно его использовать...   -  person miki725    schedule 14.07.2014


Ответы (3)


2-е ОБНОВЛЕНИЕ: возможно, вы уже обнаружили это, но в качестве обходного пути я планирую сопоставить службу для совместного использования базы данных с интерфейсом хоста (ej: с -p 5432:5432) и подключить веб-приложения к IP-адресу хоста (IP-адрес интерфейс docker0: в моих Ubuntu и CentOS IP-адрес 172.17.42.1). Если вы перезапустите контейнер postgres, IP-адрес контейнера изменится, но я буду доступен по адресу 172.17.42.1:5432. Недостатком является то, что вы открываете этот порт для всех контейнеров и теряете детальное сопоставление, которое дает вам --link.

--- СТАРЫЕ ОБНОВЛЕНИЯ:

ИСПРАВЛЕНИЕ: Docker сопоставит «postgres» с IP-адресом контейнера в файлах /etc/hosts в контейнере веб-приложения. Итак, в контейнере веб-приложения вы можете пропинговать «postgres», и он будет сопоставлен с IP-адресом.

1-е ОБНОВЛЕНИЕ: я видел, что Docker генерирует и монтирует /etc/hosts, /etc/resolv.conf и т. д., чтобы всегда иметь правильную информацию, но это не применяется при перезапуске связанного контейнера. Итак, я предположил (ошибочно), что Docker обновит файлы hosts.

-- ОРИГИНАЛЬНЫЙ (неправильный) ответ:

Добавьте --hostname=postgres-db (вы можете использовать что угодно, я использую нечто отличное от «postgres», чтобы избежать путаницы с именем контейнера):

$ docker run --name postgres --hostname postgres-db postgres/image

Docker сопоставит «postgres-db» с IP-адресом контейнера (проверьте содержимое /etc/hosts в контейнере веб-приложения).

Это позволит вам запустить «ping postgres-db» из контейнера веб-приложения. Если IP-адрес изменится, Dockers обновит /etc/hosts для вас.

В приложении Django используйте «postgres-db» вместо IP-адреса (или того, что вы используете для --hostname контейнера с PostgreSql).

Пока! Орасио

person hgdeoro    schedule 16.07.2014
comment
Пожалуйста, проверьте свои факты. Docker при линковке контейнера использует только параметр --name. --hostname используется только для вставки записи в контейнер postgres, а не в контейнер webapp. - person miki725; 16.07.2014
comment
miki725: ты прав, я путаюсь в своих тестах. Я использовал одну и ту же строку для имени и имени хоста и предположил, что указанные в «имя хоста» использовались в /etc/hosts... - person hgdeoro; 17.07.2014

Согласно https://docs.docker.com/engine/reference/commandline/run/ должна быть возможность назначить статический IP-адрес для вашего контейнера — во время создания контейнера — с помощью параметра --ip:

Пример:

docker run -itd --ip 172.30.100.104 --name postgres postgres/image

....где 172.30.100.104 — свободный IP-адрес в настраиваемой мостовой/оверлейной сети.

Затем он должен сохранить тот же IP-адрес, даже если контейнер postgres выйдет из строя или перезапустится.

Похоже, это было выпущено в Docker Engine версии 1.10 или выше, поэтому, если у вас более ранняя версия, вам необходимо сначала выполнить обновление.

person Aravind Murthy    schedule 25.08.2016

Начиная с Docker 1.0 они реализовали более сильное ощущение связанных контейнеров. Теперь вы можете использовать имя экземпляра контейнера, как если бы оно было именем хоста.

Вот ссылка

Я нашел ссылку это лучше описывает вашу проблему. И хотя на этот вопрос был дан ответ, мне интересно, может ли этот шаблон ambassador решить проблему? ... это предполагает, что посол более надежен, чем сервисы, которые связывают.

person Richard    schedule 14.07.2014
comment
пожалуйста, прочитайте мой вопрос. после перезапуска родительского контейнера его IP-адрес меняется, поэтому все, что находится в файле hosts, больше недействительно. - person miki725; 14.07.2014