Не удалось подключиться к локальному хосту изнутри контейнера.

В настоящее время я тестирую роль Ansible с помощью Molecule. По сути, Molecule запускает контейнер, совместимый с Ansible, и выполняет для него роль.

Чтобы протестировать контейнер, Molecule также встраивает модульные тесты с использованием Testinfra. Модульные тесты Python запускаются из контейнера, поэтому вы можете проверить соответствие роли.

Поскольку я работаю над ролью на основе Nginx, один из модульных тестов просто curl http://localhost:80

Я получаю следующее сообщение об ошибке в ответ:

curl: (7) Не удалось подключиться к локальному порту 80: отказано в подключении

Когда я:

  • запустить машину Vagrant
  • применить роль с Ansible
  • подключиться через vagrant ssh
  • выдать curl http://localhost команда

nginx отвечает правильно.

Поэтому я считаю, что:

  • роль работает правильно и Nginx установлен правильно
  • У Docker есть другой способ настройки сети. В некотором смысле, localhost и 127.0.0.1 больше не совпадают.

Мои вопросы следующие:

  1. Я прав?
  2. Можно ли преодолеть эту разницу, чтобы завиток работал?

2 ответа

Контейнеры Docker по умолчанию запускаются в собственном сетевом пространстве имен. Это пространство имен включает отдельный интерфейс обратной связи (127.0.0.1), который отличается от того же интерфейса на хосте и любых других контейнерах. Если вы хотите получить доступ к приложению из другого контейнера или через опубликованный порт на хосте, вам необходимо прослушивать все интерфейсы (0.0.0.0), а не петлевой интерфейс.

Еще одна проблема, с которой я часто сталкиваюсь, заключается в том, что на каком-то уровне соединения (хост или внутри контейнера) имя "localhost" сопоставляется со значением IPv6: ::1 в файле /etc/host, и где-то в этом соединении допустимо только значение IPv4 (либо там, где был опубликован порт, приложение прослушивает, либо IPv6 не включен на хосте или механизме докера). Поэтому обязательно попытайтесь подключиться к адресу IPv4 напрямую, 127.0.0.1, чтобы устранить любые потенциальные проблемы с IPv6.

Учитывая curl Команда и как ее исправить, я не могу ответить на этот вопрос без более подробной информации о том, как вы запускаете curl (находится ли он в отдельном контейнере), как вы запускаете свое приложение и как они объединяются в сети (вы создали новая сеть в докере для запуска вашего приложения и модульных тестов). Типичное решение состоит в том, чтобы создать новую сеть в Docker, запустить оба контейнера в этой сети и подключиться через включенный DNS докера к контейнеру или имени службы назначения, например curl http://my_app/,


Редактировать: основываясь на комментариях, если ваше приложение и команда curl работают внутри одного контейнера, то curl http://127.0.0.1/ должно сработать. Там нет никаких изменений, я знаю о необходимости с curl чтобы он работал внутри контейнера против виртуальной машины. Вероятно, ошибка, которую вы видите, связана с тем, что приложение не запускается и прослушивает порт должным образом, возможно, из-за гонки, когда команда curl выполняется слишком рано, или из-за неверных базовых предположений о том, как работает инструмент. Начните с изменения модульного теста, чтобы убедиться, что приложение работает и прослушивает порт с помощью команд, таких как ps -ef а также ss -lt,

На самом деле это не имеет никакого отношения к различиям между Docker и Vagrant (то есть контейнеры и виртуальные машины).

Код testInfra фактически выполняется снаружи контейнера / виртуальной машины, поэтому факт subprocess.call(['curl', 'http://localhost']) терпит неудачу.

Чтобы запустить команду из контейнера / виртуальной машины, я должен использовать:

host.check_output('curl http://localhost')
Другие вопросы по тегам