Изнутри контейнера Docker, как мне подключиться к локальному хосту машины?

Итак, у меня есть Nginx, запущенный внутри контейнера докеров, у меня есть mysql, работающий на localhost, я хочу подключиться к MySql из моего Nginx. MySql работает на локальном хосте и не предоставляет порт для внешнего мира, поэтому его привязка к локальному хосту, а не привязка к ip-адресу машины.

Есть ли способ подключиться к этому MySql или любой другой программе на локальном хосте из этого контейнера докера?

Ответ 1

Изменить: Если вы используете Docker-для-Mac или Docker-для-Windows 18. 03+, просто подключитесь к вашей службе MySQL, используя хост host.docker.internal.

Начиная с Docker 18.09.3, это не работает в Docker-для-Linux. Исправление было представлено 8 марта 2019 года и, будем надеяться, будет объединено с базой кода. До тех пор, обходной путь должен использовать контейнер, как описано в ответе Qoomon.


TL;DR

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

Примечание. Этот режим работает только в Docker для Linux согласно документации.


Обратите внимание на режимы работы с сетью док-контейнера

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

Docker run --network = "мост" (по умолчанию)

Docker по умолчанию создает мост с именем docker0. И хост-докер, и контейнеры-докеры имеют IP-адрес на этом мосту.

на хосте Docker введите sudo ip addr show docker0 вы получите вывод, похожий на:

[[email protected]:~] $ sudo ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::5484:7aff:fefe:9799/64 scope link
       valid_lft forever preferred_lft forever

Итак, у моего докера есть IP-адрес 172.17.42.1 на сетевом интерфейсе docker0.

Теперь запустите новый контейнер и получите на него оболочку: docker run --rm -it ubuntu:trusty bash и в контейнере типа ip addr show eth0 чтобы узнать, как настроен его основной сетевой интерфейс:

[email protected]:/# ip addr show eth0
863: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 66:32:13:f0:f1:e3 brd ff:ff:ff:ff:ff:ff
    inet 172.17.1.192/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6432:13ff:fef0:f1e3/64 scope link
       valid_lft forever preferred_lft forever

Здесь мой контейнер имеет IP-адрес 172.17.1.192. Теперь посмотрите на таблицу маршрутизации:

[email protected]:/# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.17.42.1     0.0.0.0         UG    0      0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 eth0

Таким образом, IP-адрес докер-хоста 172.17.42.1 устанавливается как маршрут по умолчанию и доступен из вашего контейнера.

[email protected]:/# ping 172.17.42.1
PING 172.17.42.1 (172.17.42.1) 56(84) bytes of data.
64 bytes from 172.17.42.1: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.42.1: icmp_seq=2 ttl=64 time=0.201 ms
64 bytes from 172.17.42.1: icmp_seq=3 ttl=64 time=0.116 ms

Docker run --network = "хост"

В качестве альтернативы вы можете запустить докер-контейнер с сетевыми настройками, установленными на host. Такой контейнер будет совместно использовать сетевой стек с хостом докера, и с точки зрения контейнера localhost (или 127.0.0.1) будет ссылаться на хост докера.

Помните, что любой порт, открытый в вашем контейнере докера, будет открыт на хосте докера. И это без docker run опции docker run -p или -p.

Конфигурация IP на моем хосте докера:

[[email protected]:~] $ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
       valid_lft forever preferred_lft forever

и из док-контейнера в режиме хоста:

[[email protected]:~] $ docker run --rm -it --network=host ubuntu:trusty ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
       valid_lft forever preferred_lft forever

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


Подключение к MySQL из контейнеров

режим моста

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

Для этого убедитесь, что у вас есть либо bind-address = 172.17.42.1 либо bind-address = 0.0.0.0 в вашем конфигурационном файле MySQL (my.cnf).

Если вам нужно установить переменную среды с IP-адресом шлюза, вы можете запустить следующий код в контейнере:

export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')

затем в вашем приложении используйте DOCKER_HOST_IP окружения DOCKER_HOST_IP чтобы открыть соединение с MySQL.

Примечание: если вы используете bind-address = 0.0.0.0 ваш сервер MySQL будет прослушивать соединения на всех сетевых интерфейсах. Это означает, что ваш сервер MySQL может быть доступен из Интернета; убедитесь, что настроили правила брандмауэра соответственно.

Примечание 2: если вы используете bind-address = 172.17.42.1 ваш сервер MySQL не будет прослушивать подключения к 127.0.0.1. Процессы, работающие на хосте докера, который хочет подключиться к MySQL, должны будут использовать IP-адрес 172.17.42.1.

режим хоста

Чтобы получить доступ к MySQL, работающему на хосте докера, из контейнеров в режиме хоста, вы можете сохранить bind-address = 127.0.0.1 в вашей конфигурации MySQL, и все, что вам нужно сделать, это подключиться к 127.0.0.1 из ваших контейнеров:

[[email protected]:~] $ docker run --rm -it --network=host mysql mysql -h 127.0.0.1 -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 5.5.41-0ubuntu0.14.04.1 (Ubuntu)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

примечание: используйте mysql -h 127.0.0.1 а не mysql -h localhost; в противном случае клиент MySQL будет пытаться подключиться через сокет unix.

Ответ 2

Для MacOS и Windows

Докер v 18.03 и выше (с 21 марта 2018 года)

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

Поддержка Linux в ожидании https://github.com/docker/for-linux/issues/264

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

Докер для Mac v 17.12 до v 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

Я делаю взломать похожие на вышепоставленные сообщения, чтобы локальный IP-адрес отображался в псевдониме (DNS) в контейнере. Основная проблема состоит в том, чтобы динамически получить простой script, который работает как в Linux, так и OSX на IP-адресе хоста. Я сделал это script, который работает в обеих средах (даже в дистрибутиве Linux с настройкой "$LANG" != "en_*"):

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

Итак, используя Docker Compose, полная конфигурация будет:

Запуск script (docker-run.sh):

export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)
docker-compose -f docker-compose.yml up

Докер-compose.yml:

myapp:
  build: .
  ports:
    - "80:80"
  extra_hosts:
    - "dockerhost:$DOCKERHOST"

Затем измените http://localhost на http://dockerhost в своем коде.

Для более подробного руководства по настройке DOCKERHOST script ознакомьтесь с этим сообщением с объяснением того, как это работает.

Ответ 4

Это работало для меня в стеке NGINX/PHP-FPM, не касаясь какого-либо кода или сети, где приложение просто рассчитывает подключиться к localhost

Смонтируйте mysqld.sock с хоста внутри контейнера.

Найдите местоположение файла mysql.sock на хосте, на котором запущен mysql:
netstat -ln | awk '/mysql(.*)?\.sock/{ print $9 }'

Подключите этот файл туда, где он ожидался в докере:
docker run -v/hostpath/to/mysqld.sock: /containerpath/to/mysqld.sock

Возможные расположения mysqld.sock:

/tmp/mysqld.sock
/var/run/mysqld/mysqld.sock 
/var/lib/mysql/mysql.sock
/Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP

Ответ 5

Решение для Linux (ядро> = 3.6).

Хорошо, ваш сервер localhost имеет интерфейс docker0 для док-станции с ip-адресом 172.17.0.1. Ваш контейнер запущен с сетевыми настройками по умолчанию --net = "мост".

  1. Включить route_localnet для интерфейса docker0:
    $ sysctl -w net.ipv4.conf.docker0.route_localnet=1
  2. Добавьте эти правила в iptables:
    $ iptables -t nat -I PREROUTING -I docker0 -d 172.17.0.1 -p tcp --dport 3306 -j DNAT --to 127.0.0.1:3306
    $ iptables -t filter -I INPUT -I docker0 -d 127.0.0.1 -p tcp --dport 3306 -j ACCEPT
  3. Создайте пользователя mysql с доступом от "%", что означает - от кого угодно, исключая localhost:
    CREATE USER 'user'@'%' IDENTIFIED BY 'password';
  4. Измените в своем скрипте адрес mysql-сервера на 172.17.0.1


Из документации ядра:

route_localnet - BOOLEAN: не считайте петлевые адреса в качестве марсианского источника или адресата при маршрутизации. Это позволяет использовать 127/8 для локальной маршрутизации (по умолчанию FALSE).

Ответ 6

Пока host.docker.internal не работает для каждой платформы, вы можете использовать мой контейнер в качестве шлюза NAT без какой-либо ручной настройки:

https://github.com/qoomon/docker-host

Ответ 7

Решение для Windows 10

Docker Community Edition 17.06.0-ce-win18 2017-06-28 (стабильный)

Вы можете использовать DNS-имя хоста docker.for.win.localhost, чтобы разрешить внутренний IP. (Предупреждение некоторых источников упоминает о windows но это должно быть win)

обзор
Мне нужно было сделать нечто подобное, то есть подключиться из моего контейнера Docker к моему локальному хосту, на котором были запущены Azure Storage Emulator и CosmosDB Emulator.

По умолчанию Azure Storage Emulator прослушивает 127.0.0.1, хотя вы также можете изменить его IP-адрес, я искал решение, которое работало бы с настройками по умолчанию.

Это также работает для подключения из моего контейнера Docker к SQL Server и IIS, которые работают локально на моем хосте с настройками порта по умолчанию.

Ответ 8

Для тех, кто в Windows, если вы используете сетевой драйвер моста, вам нужно будет привязать MySQL к ip-адресу сетевого интерфейса hyper-v.

Это делается через файл конфигурации в обычно скрытой папке C:\ProgramData\MySQL.

Привязка к 0.0.0.0 не будет работать. Необходимый адрес также отображается в конфигурации докера, и в моем случае это был 10.0.75.1.

Ответ 9

Изменить: я закончил разработку концепции GitHub. Проверьте: https://github.com/sivabudh/system-in-a-box


Во-первых, мой ответ ориентирован на 2 группы людей: тех, кто использует Mac, и тех, кто использует Linux.

Сетевой режим хост не работает на Mac. Вы должны использовать псевдоним IP, см. fooobar.com/questions/17859/...

Что такое режим сетевой сети? См.: https://docs.docker.com/engine/reference/run/#/network-settings

Во-вторых, для тех из вас, кто использует Linux (мой непосредственный опыт был с Ubuntu 14.04 LTS, и я скоро буду доходить до версии 16.04 LTS), да, вы можете запустить службу внутри контейнера Docker подключитесь к службам localhost, запущенным на хосте Docker (например, ваш ноутбук).

Как?

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

docker run --network="host" -id <Docker image ID>

Когда вы выполните ifconfig (вам нужно будет apt-get install net-tools ваш контейнер для ifconfig, подлежащий вызову) внутри вашего контейнера, вы увидите, что сетевые интерфейсы такие же, как и на хосте Docker (например, ваш ноутбук).

Важно отметить, что я пользователь Mac, но я запускаю Ubuntu под Parallels, поэтому использование Mac не является недостатком.; -)

И вот как вы подключаете контейнер NGINX к MySQL, работающему на localhost.

Ответ 10

Простейшее решение для Mac OSX

Просто используйте IP-адрес вашего Mac. На Mac запустите это, чтобы получить IP-адрес и использовать его из контейнера:

$ ifconfig | grep 'inet 192'| awk '{ print $2}'

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

Если вы просто хотите получить доступ к другому контейнеру докера, который прослушивает 0.0.0.0, вы можете использовать 172.17.0.1

Ответ 11

Очень просто и быстро, проверьте IP своего хоста с помощью ifconfig (linux) или ipconfig (windows), а затем создайте

докер-compose.yml

version: '3' # specify docker-compose version

services:
  nginx:
    build: ./ # specify the directory of the Dockerfile
    ports:
      - "8080:80" # specify port mapping
    extra_hosts:
      - "dockerhost:<yourIP>"

Таким образом, ваш контейнер сможет получить доступ к вашему хосту. При доступе к вашей БД не забудьте использовать имя, которое вы указали ранее, в данном случае "dockerhost" и порт вашего хоста, на котором работает БД

Ответ 12

Я не согласен с ответом Томаслевиля.

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

Привязка mysql к 0.0.0.0 откроет db для внешнего мира, что не только очень плохо, но и противоречит тому, что хочет автор оригинального вопроса. Он явно говорит: "MySql работает на локальном хосте и не подвергает порт внешнему миру, поэтому его привязка к локальному хосту"

Чтобы ответить на комментарий от ivant

"Почему бы не связать mysql с docker0?"

Это невозможно. В документации mysql/mariadb явно указано, что невозможно связать несколько интерфейсов. Вы можете привязываться только к 0, 1 или всем интерфейсам.

Как вывод, я НЕ нашел способ получить базу данных (localhost only) на хосте из контейнера докеров. Это определенно похоже на очень распространенный образец, но я не знаю, как это сделать.

Ответ 13

Вот мое решение: оно работает для моего случая

  • установить локальный сервер mysql для общего доступа по комментариям #bind-address = 127.0.0.1  в /etc/mysql/mysql.conf.d

  • перезапустить сервер mysql sudo /etc/init.d/mysql restart

  • выполните следующую команду, чтобы открыть доступ пользователя root к любому хосту mysql -uroot -proot GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION; FLUSH PRIVILEGES;

  • создать sh script: run_docker.sh

    #!bin/bash

    HOSTIP=`ip -4 addr show scope global dev eth0 | grep inet | awk '{print \$2}' | cut -d / -f 1`


      docker run -it -d --name web-app \
                  --add-host=local:${HOSTIP} \
                  -p 8080:8080 \
                  -e DATABASE_HOST=${HOSTIP} \
                  -e DATABASE_PORT=3306 \
                  -e DATABASE_NAME=demo \
                  -e DATABASE_USER=root \
                  -e DATABASE_PASSWORD=root \
                  sopheamak/springboot_docker_mysql

  
  • запустить с помощью docker-composer

    version: '2.1'
    
    

    услуги:
    tomcatwar:    extra_hosts:       - "локальный: 10.1.2.232"    изображение: sopheamak/springboot_docker_mysql
       порты:        - 8080: 8080    Окружающая среда:           - DATABASE_HOST = локальный           - DATABASE_USER = root           - DATABASE_PASSWORD = root           - DATABASE_NAME = демо           - DATABASE_PORT = 3306

Ответ 14

Ни один из ответов не сработал для меня при использовании Docker Toolbox на Windows 10 Home, но 10.0.2.2 сработал, поскольку он использует VirtualBox, который выставляет хост для виртуальной машины по этому адресу.

Ответ 15

На ум приходит несколько решений:

  1. Сначала переместите ваши зависимости в контейнеры
  2. Сделайте ваши другие сервисы доступными извне и подключитесь к ним с этим внешним IP
  3. Запустите ваши контейнеры без изоляции сети
  4. Избегайте подключения по сети, вместо этого используйте сокет, смонтированный как том

Причина, по которой это не работает "из коробки", заключается в том, что контейнеры по умолчанию запускаются с собственным сетевым пространством имен. Это означает, что localhost (или 127.0.0.1, указывающий на интерфейс обратной связи) уникален для каждого контейнера. Подключение к нему приведет к подключению к самому контейнеру, а не к сервисам, работающим за пределами докера или внутри другого контейнера докера.

Вариант 1: Если ваша зависимость может быть перемещена в контейнер, я бы сделал это в первую очередь. Это делает ваше приложение стекаемым, так как другие пытаются запустить ваш контейнер в своей среде. И вы по-прежнему можете публиковать порт на своем хосте, где другие службы, которые не были перенесены, все еще могут достичь его. Вы даже можете опубликовать порт в интерфейсе localhost на вашем док-хосте, чтобы избежать его внешнего доступа с помощью синтаксиса, например: -p 127.0.0.1:3306:3306 для опубликованного порта.

Вариант 2. Существует множество способов определения IP-адреса хоста внутри контейнера, но у каждого из них есть ограниченное число сценариев, в которых они работают (например, требуется Docker для Mac). Наиболее переносимый вариант - ввести IP-адрес вашего хоста в контейнер с помощью чего-то вроде переменной среды или файла конфигурации, например:

docker run --rm -e "HOST_IP=$(ip r s 0/0 | awk '{print $3}')" ...

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

Вариант 3: Запуск без изоляции сети, т.е. с --net host, означает, что ваше приложение работает в пространстве имен сети хоста. Это меньше изолирует контейнер, и это означает, что вы не можете получить доступ к другим контейнерам через общую сеть докеров с DNS (вместо этого вам нужно использовать опубликованные порты для доступа к другим приложениям в контейнерах). Но для приложений, которым требуется доступ к другим службам на хосте, которые прослушивают только 127.0.0.1 на хосте, это может быть самым простым вариантом.

Вариант 4. Различные сервисы также разрешают доступ через сокет на основе файловой системы. Этот сокет может быть подключен к контейнеру в качестве тома с привязкой, что позволяет получить доступ к службе хоста, не выходя в сеть. Для доступа к механизму докера вы часто видите примеры монтирования /var/run/docker.sock в контейнер (предоставляя этому контейнеру корневой доступ к хосту). С mysql вы можете попробовать что-то вроде -v/var/run/mysqld/mysqld.sock: /var/run/mysqld/mysql.sock а затем подключиться к localhost который mysql преобразует в использование сокета.

Ответ 16

Это не ответ на актуальный вопрос. Так я решил похожую проблему. Решение полностью основано на: Определите Docker Container Networking, чтобы контейнеры могли общаться. Спасибо Ник Рабой

Оставьте это здесь для других, которые могут захотеть делать вызовы REST между одним контейнером и другим. Отвечает на вопрос: что использовать вместо localhost в среде докера?

Узнайте, как ваша сеть выглядит как docker network ls

Создайте новую сетевую docker network create -d my-net

Запустите первый docker run -d -p 5000:5000 --network="my-net" --name "first_container" <MyImage1:v0.1> контейнера: docker run -d -p 5000:5000 --network="my-net" --name "first_container" <MyImage1:v0.1>

Проверьте сетевые настройки для первого контейнерного docker inspect first_container. "Сети": должна быть "моя сеть"

Запустите второй контейнерный docker run -d -p 6000:6000 --network="my-net" --name "second_container" <MyImage2:v0.1>

Проверьте настройки сети для второго контейнерного docker inspect second_container. "Сети": должна быть "моя сеть"

ssh во второй контейнерный docker exec -it second_container sh или docker exec -it second_container bash.

Внутри второго контейнера вы можете ping first_container первый контейнер с помощью ping first_container. Кроме того, ваши вызовы кода, такие как http://localhost:5000 могут быть заменены на http://first_container:5000

Ответ 17

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

docker run --rm alpine ip route | awk 'NR==1 {print $3}'

Это будет более последовательным, поскольку вы всегда используете альпийский язык для запуска команды.

Подобно ответу Мариано, вы можете использовать ту же команду для установки переменной окружения

DOCKER_HOST=$(docker run --rm alpine ip route | awk 'NR==1 {print $3}') docker-compose up

Ответ 18

CGroups и пространства имен играют важную роль в экосистеме контейнеров.

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

Вот основное понимание подхода к решению, за которым вы могли бы следовать,

Использовать сетевое пространство имен

Когда контейнер появляется из образа, определяется и создается сетевой интерфейс. Это дает уникальному IP-адресу контейнера и интерфейсу.

$ docker run -it alpine ifconfig

Изменив пространство имен на хост, сети cotainers не остаются изолированными от своего интерфейса, процесс будет иметь доступ к сетевому интерфейсу хост-машин.

$ docker run -it --net=host alpine ifconfig

Если процесс прослушивает порты, они будут прослушиваться на интерфейсе хоста и отображаться в контейнере.

Использовать пространство имен PID Путем изменения пространства имен Pid позволяет контейнеру взаимодействовать с другим процессом, выходящим за пределы его обычной области.

Этот контейнер будет работать в своем собственном пространстве имен.

$ docker run -it alpine ps aux

Изменив пространство имен на хост, контейнер также может видеть все остальные процессы, запущенные в системе.

$ docker run -it --pid=host alpine ps aux

Совместное использование пространства имен

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

Первым контейнером является nginx-сервер. Это создаст новое пространство имен для сетей и процессов. Этот контейнер свяжет себя с портом 80 вновь созданного сетевого интерфейса.

$ docker run -d --name http nginx:alpine

Другой контейнер теперь может повторно использовать это пространство имен,

$ docker run --net=container:http mohan08p/curl curl -s localhost

Кроме того, этот контейнер может видеть интерфейс с процессами в совместно используемом контейнере.

$ docker run --pid=container:http alpine ps aux

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

Ответ 19

Для Windows Machine: -

Выполните команду ниже, чтобы случайно открыть порт докера в течение времени сборки

$docker run -d --name MyWebServer -P mediawiki

enter image description here

enter image description here

В приведенном выше списке контейнеров вы можете увидеть порт, назначенный как 32768. Попробуйте получить доступ

localhost:32768 

Вы можете увидеть страницу mediawiki

Ответ 20

Для Linux, где вы не можете изменить интерфейс, к которому привязывается служба localhost

Есть две проблемы, которые нам нужно решить

  1. Получение IP-адреса хоста
  2. Сделать наш сервис localhost доступным для Docker

Первая проблема может быть решена с помощью qoomon docker-host image, как указано в других ответах.

Вам нужно будет добавить этот контейнер в ту же мостовую сеть, что и ваш другой контейнер, чтобы вы могли получить к нему доступ. Откройте терминал внутри своего контейнера и убедитесь, что вы можете пропинговать dockerhost.

bash-5.0# ping dockerhost
PING dockerhost (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.523 ms

Теперь сложная задача - сделать сервис доступным для докера.

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

Проблема заключается в том, что наш контейнер будет иметь доступ только к службам, которые привязаны ко всем интерфейсам, таким как SSH:

bash-5.0# telnet dockerhost 22
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

Но сервисы, привязанные только к localhost, будут недоступны:

bash-5.0# telnet dockerhost 1025
telnet: can't connect to remote host (172.20.0.2): Connection refused

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

Во-первых, нам нужно найти имя сети моста, которую использует докер с ifconfig. Если вы используете неназванный мост, это будет просто docker0. Однако, если вы используете именованную сеть, у вас будет мост, начинающийся с br-, который вместо этого будет использовать докер. Мой br-5cd80298d6f4.

Как только у нас будет имя этого моста, нам нужно разрешить маршрутизацию от этого моста к localhost. По умолчанию это отключено по соображениям безопасности:

sysctl -w net.ipv4.conf.<bridge_name>.route_localnet=1

Теперь настройте наше правило iptables. Поскольку наш контейнер может получать доступ только к портам в сети Docker Bridge, мы будем делать вид, что наш сервис фактически связан с портом в этой сети.

Для этого мы направим все запросы на <docker_bridge>:port на localhost:port

iptables -t nat -A PREROUTING -p tcp -i <docker_bridge_name> --dport <service_port> -j DNAT --to-destination 127.0.0.1:<service_port>

Например, для моего сервиса на порту 1025

iptables -t nat -A PREROUTING -p tcp -i br-5cd80298d6f4 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025

Теперь вы сможете получить доступ к своему сервису из контейнера:

bash-5.0# telnet dockerhost 1025
220 127.0.0.1 ESMTP Service Ready

Ответ 21

Пока исправление не объединено с master веткой, чтобы получить IP хоста, просто запустите изнутри контейнера:

ip -4 route list match 0/0 | cut -d' ' -f3

(как предложено @Mahoney здесь).

Ответ 22

Запуск docker-контейнера mysql в сети хоста (путем запуска docker с "--network host") кажется простым решением.

Ответ 23

Я решил это, создав пользователя в MySQL для контейнера ip:

$ sudo mysql<br>
mysql> create user 'username'@'172.17.0.2' identified by 'password';<br>
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on database_name.* to 'username'@'172.17.0.2' with grant option;<br>
Query OK, 0 rows affected (0.00 sec)

$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
<br>bind-address        = 172.17.0.1

$ sudo systemctl restart mysql.service

Затем на контейнере: jdbc:mysql://<b>172.17.0.1</b>:3306/database_name

Ответ 24

Вы можете использовать ngrok, чтобы создать безопасный туннель на вашей машине localhost, а затем выставить этот туннель в контейнер докеров.

ngrok может свободно использовать с 05/22/2017.

Шаги:

1) перейдите к ngrok

2) download клиент ngrok и следуйте инструкциям по установке

3) SIGN UP для учетной записи, и они предоставят токен аутентификации. Требуется регистрация, потому что ngrok предоставляет вам туннель туннеля tcp после регистрации. Для регистрации не требуется никаких средств или кредитной карты.

4) в вашем терминале do ngrok tcp 3306. 3306 - это порт, который mysql работает на моем локальном, вы можете сделать это и с любым другим портом.

5) Вы получите адрес с шага 4, например: tcp://0.tcp.ngrok.io:10117. Это туннельное соединение с вашей локальной машиной. 0.tcp.ngrok.io отображается на ваш localhost, а порт 10117 сопоставляется с вашим локальным портом 3306. Теперь вы можете получить доступ к локальному порту 3306 из любого места, используя этот адрес, включая любой контейнер докеров, запущенный на этом компьютере. В вашем контейнере докеров (где бы он ни находился), предположив, что клиент mysql уже установлен, выполните следующие действия:

mysql --host 0.tcp.ngrok.io --port 10117 -u root

Вы сможете войти в свою учетную запись root своего локального компьютера изнутри контейнера докеров!

Я писал об этом решении подробнее... здесь