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

Как получить доступ к порту хоста из контейнера докеров

У меня есть докер-контейнер, в котором работают дженкинсы. В рамках процесса сборки мне нужно получить доступ к веб-серверу, который выполняется локально на главной машине. Есть ли способ, которым веб-сервер хоста (который может быть настроен для работы на порту) может быть открыт контейнеру jenkins?

EDIT: я запускаю docker изначально на машине Linux.

UPDATE:

В дополнение к @larsks ответьте ниже, чтобы получить IP-адрес хост-IP с хост-машины, я делаю следующее:

ip addr show docker0 | grep -Po 'inet \K[\d.]+'
4b9b3361

Ответ 1

При запуске Docker изначально на Linux вы можете получить доступ к службам хоста, используя IP-адрес интерфейса docker0. Изнутри контейнера это будет ваш маршрут по умолчанию.

Например, в моей системе:

$ ip addr show docker0
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::f4d2:49ff:fedd:28a0/64 scope link 
       valid_lft forever preferred_lft forever

И внутри контейнера:

# ip route show
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0  src 172.17.0.4 

Довольно легко извлечь этот IP-адрес с помощью простой оболочки script:

#!/bin/sh

hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip

Вам может потребоваться изменить правила iptables на вашем хосте, чтобы разрешить соединения из контейнеров Docker. Что-то вроде этого будет делать Хитрость:

# iptables -A INPUT -i docker0 -j ACCEPT

Это позволит получить доступ к любым портам на хосте от Docker контейнеры. Обратите внимание:

  • Правила iptables упорядочены, и это правило может или не может выполнять правильная вещь в зависимости от того, какие другие правила приходят перед ней.

  • вы сможете получить доступ только к хост-сервисам, которые либо (а) прослушивание INADDR_ANY (aka 0.0.0.0) или явно прослушивание интерфейса docker0.

Ответ 2

Для macOS и Windows

Docker v 18.03 и выше (с 21 марта 2018 г.)

Используйте свой внутренний IP-адрес или подключитесь к специальному DNS-имени host.docker.internal который будет host.docker.internal во внутренний IP-адрес, используемый хостом.

Ожидается поддержка Linux https://github.com/docker/for-linux/issues/264

MacOS с более ранними версиями Docker

Докер для Mac v 17.12 до 18.02

То же, что и выше, но вместо этого используйте docker.for.mac.host.internal.

Докер для Mac с 17.06 по 17.11

То же, что и выше, но вместо этого используйте docker.for.mac.localhost.

Докер для Mac 17.05 и ниже

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

sudo ifconfig lo0 alias 123.123.123.123/24

Затем убедитесь, что ваш сервер прослушивает IP-адрес, упомянутый выше или 0.0.0.0. Если он прослушивает localhost 127.0.0.1 он не примет соединение.

Затем просто укажите свой док-контейнер на этот IP, и вы получите доступ к хост-машине!

Для тестирования вы можете запустить что-то вроде curl -X GET 123.123.123.123:3000 внутри контейнера.

Псевдоним будет сбрасываться при каждой перезагрузке, поэтому при необходимости создайте сценарий запуска.

Решение и дополнительная документация здесь: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

Ответ 3

Используйте --net="host" в вашей команде docker run --net="host", тогда localhost в вашем контейнере Docker будет указывать на ваш хост Docker.

Ответ 4

Решение с docker-compose: для доступа к сервису на основе хоста вы можете использовать параметр network_mode https://docs.docker.com/compose/compose-file/#network_mode

version: '3'
services:
  jenkins:
    network_mode: host

Ответ 5

В настоящее время самый простой способ сделать это на Mac и Windows - использовать host host.docker.internal, который разрешает IP-адрес хост-машины. К сожалению, он не работает на Linux (по состоянию на апрель 2018 года).

Ответ 6

Я создал Docker-контейнер для выполнения именно этого https://github.com/qoomon/docker-host

Затем вы можете просто использовать имя контейнера dns для доступа к хост-системе, например curl http://dockerhost:9200

Ответ 7

Мы обнаружили, что более простым решением для всего этого сетевого мусора является использование доменного сокета для службы. Если вы все равно пытаетесь подключиться к хосту, просто смонтируйте сокет как том, и вы уже в пути. Для postgresql это было так просто:

docker run -v /var/run/postgresql:/var/run/postgresql

Затем мы просто настраиваем соединение с нашей базой данных, чтобы использовать сокет вместо сети. Буквально так просто.

Ответ 8

Вы можете получить доступ к локальному веб-серверу, который работает на вашем хост-компьютере, двумя способами.

  1. Подход 1 с публичным IP

    Используйте общедоступный IP-адрес хост-машины для доступа к веб-серверу в контейнере док-станции Jenkins.

  2. Подход 2 с хост-сетью

    Используйте "--net host" для добавления док-контейнера Jenkins в стек сети хоста. Контейнеры, развернутые в стеке хоста, имеют полный доступ к интерфейсу хоста. Вы можете получить доступ к локальному веб-серверу в Docker-контейнере с частным IP-адресом хост-машины.

NETWORK ID          NAME                      DRIVER              SCOPE
b3554ea51ca3        bridge                    bridge              local
2f0d6d6fdd88        host                      host                local
b9c2a4bc23b2        none                      null                local

Запустите контейнер с хост-сетью. Eg: docker run --net host -it ubuntu и запустите ifconfig чтобы получить список всех доступных сетевых IP-адресов, доступных из док-контейнера.

Например: я запустил сервер nginx на своем локальном хост-компьютере и смог получить доступ к URL-адресам веб-сайтов nginx из док-контейнера Ubuntu.

docker run --net host -it ubuntu

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a604f7af5e36        ubuntu              "/bin/bash"         22 seconds ago      Up 20 seconds                           ubuntu_server

Доступ к веб-серверу Nginx (работающему на локальном хосте) из док-контейнера Ubuntu с IP-адресом частной сети.

[email protected]:/# curl 192.168.x.x -I
HTTP/1.1 200 OK
Server: nginx/1.15.10
Date: Tue, 09 Apr 2019 05:12:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Mar 2019 14:04:38 GMT
Connection: keep-alive
ETag: "5c9a3176-264"
Accept-Ranges: bytes

Ответ 9

Я изучил различные решения и нашел это наименее хакерское решение:

  1. Определите статический IP-адрес для IP-адреса шлюза моста.
  2. Добавьте IP-адрес шлюза в качестве дополнительной записи в директиву extra_hosts.

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

Вот пример Docker Compose:

version: '2.3'

services:
  redis:
    image: "redis"
    extra_hosts:
      - "dockerhost:172.20.0.1"

networks:
  default:
    ipam:
      driver: default
      config:
      - subnet: 172.20.0.0/16
        gateway: 172.20.0.1

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

Ответ 10

Когда у вас есть два изображения докеров, которые уже созданы, и вы хотите связать два контейнера друг с другом.

Для этого вы можете удобно запускать каждый контейнер со своим собственным именем и использовать флаг -link для обеспечения связи между ними. Вы не получите этого во время сборки докеров.

Когда вы находитесь в таком сценарии, как я, и это ваш

docker build -t "centos7/someApp" someApp/ 

Это ломается, когда вы пытаетесь

curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz

и вы застряли на "curl/wget", не возвращающем "маршрут к хосту".

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

Объяснение этого подробно описано в следующей документации.

http://www.dedoimedo.com/computers/docker-networking.html

Приводятся два быстрых обхода, которые помогут вам двигаться, снижая сетевую безопасность.

Самая простая альтернатива - просто отключить брандмауэр - или разрешить все. Это означает, что нужно выполнить необходимую команду, которая может быть остановлена ​​на системной остановке firewalld, iptables -F или эквивалентной.

Надеемся, что эта информация поможет вам.