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

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

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

43 ответа

Решение

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

Начиная с Docker 18.04, это не работает в Docker-для-Linux.


TLDR

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


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

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

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

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

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

[vagrant@docker:~] $ 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 чтобы узнать, как настроен его основной сетевой интерфейс:

root@e77f6a1b3740:/# 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, Теперь посмотрите на таблицу маршрутизации:

root@e77f6a1b3740:/# 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 устанавливается как маршрут по умолчанию и доступен из вашего контейнера.

root@e77f6a1b3740:/# 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"

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

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

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

[vagrant@docker:~] $ 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

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

[vagrant@docker:~] $ 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 прослушивает соединения на 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 переменная окружения, чтобы открыть соединение с MySQL.

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

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

режим хоста

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

[vagrant@docker:~] $ 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.

Для macOS и Windows

Docker 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 до 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, Если он слушает на локальном хосте 127.0.0.1 он не примет соединение.

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

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

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

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

С помощью

host.docker.internal

вместо того

localhost

у меня работает безупречно.

Я сделал хак, похожий на приведенные выше посты, чтобы получить локальный IP для сопоставления с псевдонимом (DNS) в контейнере. Основная проблема заключается в том, чтобы динамически получить с помощью простого сценария, который работает как в Linux, так и в OSX, IP-адрес хоста. Я сделал этот скрипт, который работает в обеих средах (даже в дистрибутиве 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, полная конфигурация будет:

Скрипт запуска (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

docker-compose.yml:

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

Тогда поменяй http://localhost в http://dockerhost в вашем коде.

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

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

Хорошо, ваш локальный сервер имеет интерфейс Docker по умолчанию с IP-адресом 172.17.0.1. Ваш контейнер запущен с сетевыми настройками по умолчанию --net = "bridge".

  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).

Это сработало для меня в стеке 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

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

Самое простое решение для Mac OSX

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

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

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

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

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

  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 в контейнер (предоставляя этому контейнеру root доступ к хосту). С MySQL вы можете попробовать что-то вроде -v /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysql.sock а затем подключиться к localhost который MySQL конвертирует в использование сокета.

Очень просто и быстро, проверьте 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" и порт вашего хоста, на котором работает БД

Решение для 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 оба работают локально на моем хосте с настройками порта по умолчанию.

Для окон,

Я изменил URL-адрес базы данных в конфигурации Spring: spring.datasource.url=jdbc:postgresql://host.docker.internal:5432/apidb

Затем создайте образ и запустите. У меня это сработало.

Это не ответ на актуальный вопрос. Так я решил похожую проблему. Решение полностью основано на: Определите 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 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, Кроме того, ваш код звонков, таких как http://localhost:5000 можно заменить на http://first_container:5000

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

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

Нам нужно решить две проблемы

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

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

Вам нужно будет добавить этот контейнер в ту же сеть моста, что и ваш другой контейнер, чтобы вы могли получить к нему доступ. Откройте терминал внутри вашего контейнера и убедитесь, что вы можете пинговать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.

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

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

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

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

Для этого мы будем пересылать все запросы на <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

Если вы работаете с --net=host, localhost должен работать нормально. Если вы используете сеть по умолчанию, используйте статический IP-адрес 172.17.0.1.

Смотрите это - /questions/44664970/chto-takoe-linux-ekvivalent-dockerformachostinternal/44664997#44664997

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

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

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

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


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

Режим сети хоста не работает на Mac. Вы должны использовать IP-псевдоним, см.: /questions/22894696/kak-podklyuchitsya-k-lokalnomu-uzlu-mashinyi-iz-kontejnera-docker/22894704#22894704

Что такое режим сети хоста? Смотрите: https://docs.docker.com/engine/reference/run/

Во-вторых, для тех из вас, кто использует 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,

Сначала ознакомьтесь с этим ответом, чтобы узнать о вариантах решения этой проблемы. Но если вы используете docker-compose можете добавить network_mode: host к вашим услугам, а затем используйте 127.0.0.1для подключения к локальному хосту. Это лишь один из вариантов, описанных в ответе выше. Ниже вы можете узнать, как я модифицировал docker-compose.yml из https://github.com/geerlingguy/php-apache-container.git:

 ---
 version: "3"
 services:
   php-apache:
+    network_mode: host
     image: geerlingguy/php-apache:latest
     container_name: php-apache
...

+ указывает на добавленную мной строку.


[Дополнительная информация] Это также работало в версии 2.2. и "хост" или просто "хост" оба работают в docker-compose.

 ---
 version: "2.2"

 services:
   php-apache:
+    network_mode: "host"
        or
+    network_mode: host
...

Я не согласен с ответом Thomasleveil.

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

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

Ответить на комментарий от ivant

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

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

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

Попробуй это:

version: '3.5'
services:
  yourservice-here:
    container_name: container_name
    ports:
      - "4000:4000"
    extra_hosts: # <---- here
      - localhost:192.168.1.202
      - or-vitualhost.local:192.168.1.202

Получить 192.168.1.202, использует ifconfig

Это сработало для меня. Надеюсь на эту помощь!

Через 7 лет был задан вопрос, то ли докер поменялся, то ли никто так не пробовал. Поэтому я включу свой собственный ответ.

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

  • использовать ipconfigили же ifconfigна вашем хосте и запишите все IP-адреса. Как минимум два из них могут использоваться контейнером.

    • У меня есть фиксированный локальный сетевой адрес на адаптере WiFi LAN: 192.168.1.101. Это должно быть 10.0.1.101. результат будет меняться в зависимости от вашего роутера
    • Я использую WSL в Windows, и у него есть собственный vEthernetадрес: 172.19.192.1
  • использовать host.docker.internal. Большинство ответов имеют ту или иную форму в зависимости от ОС. Название предполагает, что теперь оно используется докером во всем мире.

Третий вариант — использовать WAN-адрес машины или, другими словами, IP-адрес, предоставленный поставщиком услуг. Однако это может не сработать, если IP-адрес не является статическим и требует настройки маршрутизации и брандмауэра.

Вам нужно знать шлюз! Мое решение с локальным сервером заключалось в том, чтобы выставить его под0.0.0.0:8000, затем запустите докер с подсетью и запустите контейнер, например:

docker network create --subnet=172.35.0.0/16 --gateway 172.35.0.1 SUBNET35
docker run -d -p 4444:4444 --net SUBNET35 <container-you-want-run-place-here>

Итак, теперь вы можете получить доступ к своей петле через http://172.35.0.1:8000

Connect to the gateway address.

      ❯ docker network inspect bridge | grep Gateway
                    "Gateway": "172.17.0.1"

Make sure the process on the host is listening on this interface (i.e 172.17.0.1 in my machine). It works for me in linux.

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

  • установить локальный сервер 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: run_docker.sh

    #! Бен / Баш

    HOSTIP=`ip -4 addr show scope глобальный dev eth0 | grep inet | awk '{print \$2}' | cut -d / -f 1`


      docker run -it -d --name веб-приложение \
                  --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

    версия: '2.1'

    Сервисы:
    tomcatwar: extra_hosts: - "местный:10.1.2.232" изображение: sopheamak/springboot_docker_mysql
    порты: - 8080:8080 среда: - DATABASE_HOST=local - DATABASE_USER=root - DATABASE_PASSWORD=root - DATABASE_NAME=demo - DATABASE_PORT=3306

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

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

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

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

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

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

вы можете использовать сетевой псевдоним для вашей машины

ОС X

      sudo ifconfig lo0 alias 123.123.123.123/24 up

ЛИНУКС

      sudo ifconfig lo:0  123.123.123.123 up

то из контейнера можно увидеть машину по123.123.123.123

Я решил это, создав пользователя в 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

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

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

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

Другие вопросы по тегам