Подтвердить что ты не робот

Почему я не могу скрутить один контейнер докера из другого через хост

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

Вот моя настройка. У меня есть моя машина для разработчиков. И у меня есть докерная машина с двумя контейнерами. CONT_A прослушивает и публикует веб-службу на порту 3000.

DEV-MACHINE

HOST (Public IP = 111.222.333.444)
  CONT_A (Publish 3000)
  CONT_B

введите описание изображения здесь

На моей машине dev (совершенно другая машина)

Я могу свернуть без проблем

curl http://111.222.333.444:3000 --> OK

Когда я SSH в HOST

Я могу завивать без каких-либо проблем

curl http://111.222.333.444:3000 --> OK

Когда я выполняю внутри CONT_B

Невозможно, просто перерыв. Пинг в порядке, хотя...

docker exec -it CONT_B bash
$ curl http://111.222.333.444:3000 --> TIMEOUT
$ ping 111.222.333.444 --> OK

Почему?

Ubuntu 16.04, Docker 1.12.3 (настройка сети по умолчанию)

4b9b3361

Ответ 1

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

//create network    
docker network create --driver overlay --subnet=10.0.9.0/24 my-net
//Start Container A
docker run -d --name=A --network=my-net producer:latest
//Start Container B
docker run -d --name=B --network=my-net consumer:latest

//Magic has occured
docker exec -it B /bin/bash
> curl A:3000 //MIND BLOWN!

Тогда внутри контейнера вы можете просто свернуть имя хоста A, и оно разрешится для вас (даже когда вы начнете выполнять масштабирование и т.д.)

Если вы не заинтересованы в использовании Docker Swarm, вы все равно можете использовать и унаследованные ссылки Docker:

docker run -d --name B --link A:A consumer:latest

который связывает любые открытые (не опубликованные) порты в вашем контейнере.

И, наконец, если вы начнете переходить в производство... забудьте о ссылках и оверлейных сетях в целом... используйте Kubernetes :-) Немного сложнее при начальной настройке, но они вводят множество концепций и инструментов, чтобы сделать связывание и масштабирование кластеров контейнеров намного проще! Но это только мое личное мнение.

Ответ 2

У меня была аналогичная проблема: у меня есть сервер nginx в одном контейнере (разрешает его использование в сети) с несколькими серверными блоками и cron, установленный в другом контейнере (позволяет называть его cron). Я использую докер. Я хотел время от времени использовать завиток от cron до web, чтобы выполнить какой-либо php script в одном из приложений. Он должен выглядеть следующим образом:

curl http://app1.example.com/some_maintance.php

Но через некоторое время я всегда становился недосягаемым.

Первым решением было обновление /etc/hosts в контейнере cron и добавление:

1.2.3.4 app1.example.com

где 1.2.3.4 является ip для веб-контейнера, и он работал - но это взломать - также насколько я знаю, такие обновления вручную не поощряются. Вы должны использовать extra_hosts в docker compose, для чего требуется явно указывать IP-адрес вместо имени контейнера для указания IP-адреса.

Я попытался использовать решение для пользовательских сетей, которое, как я видел, является правильным способом справиться с этим, но мне так и не удалось. Если я когда-нибудь узнаю, как это сделать, я обещаю обновить этот ответ.

Наконец, я использовал функцию зависания, чтобы указать IP-адрес сервера, и передаю имя домена в виде заголовка в отдельном параметре:

curl -H'Host: app1.example.com' web/some_maintance.php

не очень красиво, но работает.

(здесь web - это имя моего контейнера nginx)

Ответ 3

--network host контейнер B с аргументом --network host, вы можете просто получить доступ к контейнеру A с помощью localhost, публичный ip не требуется.

> docker run -d --name containerB --network host yourimagename:version

После того, как вы запустите контейнер B с помощью вышеуказанной команды, вы можете попробовать свернуть контейнер A из контейнера B следующим образом.

> docker exec -it containerB /bin/bash
> curl http://localhost:3000