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

avatar
Phil
20 июня 2014 в 03:54
1419155
36
2305

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

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

Этот вопрос отличается от вопроса «Как получить IP-адрес хоста докера изнутри контейнера докера» из-за того, что IP-адрес хоста докера может быть публичным IP или частным IP в сети, которая могут быть доступны или недоступны из контейнера докеров (я имею в виду общедоступный IP-адрес, если он размещен на AWS или что-то в этом роде). Даже если у вас есть IP-адрес хоста докера, это не означает, что вы можете подключиться к хосту докера из контейнера, учитывая, что этот IP-адрес, поскольку ваша сеть Docker может быть оверлей, хостом, мостом, macvlan, none и т. Д., Что ограничивает доступность этот IP-адрес.

Источник
ivant
20 июня 2014 в 11:42
7

Почему бы также не привязать mysql к docker0?

Lokesh S
17 сентября 2018 в 15:14
3

Для Windows Machine: - $ docker run -d --name MyWebServer -P httpd

Nick Grealy
7 ноября 2019 в 00:25
0

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

FreeSoftwareServers
17 мая 2020 в 20:26
9

Без network: host вы не можете вернуться из контейнера на хост. Только хост в контейнер. Это основная идеология контейнеров. Они изолированы как по соображениям стабильности, так и по соображениям безопасности.

Antonio Petricca
26 мая 2021 в 07:51
0

Привет, coderhelper.com/a/61001152/418599 - популярное решение для получения действительного внутреннего хоста докера.

Ответы (36)

avatar
Thomasleveil
20 июня 2014 в 11:46
3180

Изменить:

Если вы используете Docker-for-mac или Docker-for-Windows 18.03+, просто подключитесь к своей службе mysql, используя хост host.docker.internal (вместо 127.0.0.1 в строке подключения).

Если вы используете Docker-for-Linux 20.10.0+, вы также можете использовать хост host.docker.internal , если вы запустили свой контейнер Docker с параметром --add-host host.docker.internal:host-gateway.

В противном случае прочтите ниже


TLDR

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

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


Примечание о сетевых режимах контейнера докеров

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

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

Docker по умолчанию создает мост с именем 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 или -P docker 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 прослушивает соединения по 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, чтобы открыть соединение с 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 из ваших контейнеров:

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

Ben
12 мая 2015 в 05:45
20

Спасибо за столь подробный ответ! Из того, что я собрал, использование режима хоста - единственный способ получить эту функциональность через localhost. Я не пробовал, но предполагаю, что вы можете создать отдельную сеть для подключения контейнеров через их собственный мост, предлагая им общий «localhost».

Thomasleveil
12 мая 2015 в 08:26
2

Также имеется руководство по расширенным сетевым технологиям по адресу docs.docker.com/articles/networking

Charlie Dalsass
1 октября 2015 в 22:19
32

Примечание для пользователей OSX: сначала войдите в свою виртуальную машину docker (boot2docker), используя «docker-machine ssh default», затем запустите «sudo ip addr show docker0». Продолжайте оттуда следовать инструкциям Томаса.

zx1986
30 июня 2016 в 03:35
36

Я запускаю Docker для Mac, и больше нет ни 172.17.42.1, ни docker0. Это был шлюз 172.17.0.1, и даже не может telnet 172.17.0.1 3306

Jonah
10 августа 2016 в 07:41
3

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

chx
2 сентября 2016 в 05:30
34

Вы можете смонтировать сокет mysql в контейнер вместо сети, например -v /var/run/mysqld/mysqld.sock:/tmp/mysql.sock this.

TheJKFever
9 февраля 2017 в 19:10
9

Может ли кто-нибудь решить ситуацию, когда у вас запущен Docker на Mac и не используется boot2docker, как таковой интерфейс docker0 отсутствует?

ospider
13 июля 2017 в 09:16
1

если вы получаете отказ в доступе изнутри контейнера докеров, вам может потребоваться разрешить root-доступ за пределами localhost с GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

MikeV
21 марта 2018 в 23:50
3

Для всех, кто пытается подключиться к хост-службе и запускает Docker для Mac. Существует специальное DNS-имя для Mac docker.for.mac.host.internal, которое преобразуется во внутренний IP-адрес, используемый хостом. источник

funseiki
19 апреля 2018 в 20:33
3

Последняя версия Docker поддерживает host.docker.internal в качестве доменного имени из контейнера (согласно последнему обновлению в ответе @Janne Annala). В дальнейшем это кажется более общим решением, когда вам все еще нужен некоторый уровень изоляции между сетью контейнера и хоста.

Thomasleveil
20 апреля 2018 в 05:55
4

@funseiki обратите внимание, что для docker 18.04.0-ce host.docker.internal не работает для Linux. Он работает только для docker-for-Windows и docker-for-mac. См. github.com/docker/for-linux/issues/264

Eric
2 мая 2018 в 17:26
3

--net=host прерывает трансляцию опубликованного порта, так что если контейнер предоставляет порт 80 (используя --publish XXX:80 или проще -p XXX:80, тогда, если служба на хосте уже привязана к порту 80 (экземпляр докера или собственная служба хоста), тогда контейнер не сможет привязать порт 80. Так что это ни в коем случае не годится.

99Sono
17 ноября 2019 в 10:02
0

если вы используете Mac, хост-система не будет показывать вам на хосте (Mac) IP-адрес для сети brdige. Поэтому, когда вы хотите связаться с Mac, докер-машиной, вам нужно использовать переадресацию порта -p AnyPort1: Anyport2 и использовать localhost. С другой стороны, с док-машины будет работать что-то вроде этого: telnet host.docker.internal 445

Zephaniah Grunschlag
8 мая 2020 в 15:38
0

Вы можете видеть направления Mac, начиная с версии Docker 18.03, ссылаясь на host.docker.internal здесь

Loek
21 мая 2020 в 09:35
0

Просто попробовал --network="host" в Docker Desktop для Windows (2.3.0.2), и он работал отлично.

walt_die
12 июня 2020 в 05:25
0

Это с достаточным отрывом один из 5 лучших ответов, которые я получил на SO! Thomasleveil спасибо за вашу ATI (внимание, время и интерес) <3 @ iam.Carrot огромное спасибо за поддержание этого ответа: plusone: и: thumbsup:

Peter Tirrell
2 июля 2020 в 13:58
0

Это частично решило мою проблему - host.docker.internal работал отлично. Однако я пытаюсь получить доступ к сайту IIS, размещенному локально, и получаю сообщение об ошибке SSL, потому что, конечно, у меня нет сертификата SSL для host.docker.internal. Есть ли способ создать локальный сертификат для этого использования?

massaskillz
23 июля 2020 в 19:52
0

@PeterTirrell У меня та же проблема, что вы описали. Вы смогли найти решение?

Peter Tirrell
27 июля 2020 в 20:51
1

@massaskillz, правда, не знал. В моем случае я использовал внутренний класс-оболочку вокруг HttpClient для выполнения вызова, поэтому я настроил HttpClientHandler.ServerCertificateCustomValidationCallback, чтобы в основном перехватывать любые ошибки проверки SSL и игнорировать их, если RequestUri содержит host.docker.internal. Это взломано, но заставило меня отладить.

Shamim
5 августа 2020 в 12:10
0

Этот ответ заслуживает 100 голосов, но я не могу этого сделать.

Don Rhummy
21 сентября 2020 в 19:49
1

Запуск докера типа: docker run --rm -d -p 5000:5000/tcp mytestimage:latest --network="host" не работает. Я получаю сообщение об ошибке, что не удается подключиться к 127.0.0.1. Единственное, что сработало, было в моем коде C # с использованием host.docker.internal вместо localhost или 127.0.0.1. Есть идеи, почему это не работает на Docker в Windows?

kzu
22 мая 2021 в 18:48
1

Замечательный ответ! Я просто хотел добавить, что для того, чтобы это работало в docker-compose.yml, вы должны добавить запись extra-hosts с с host.docker.internal:host-gateway, как и с docker run --add-host. Возможно, @Thomasleveil тоже мог бы добавить это в верхнюю правку. Мне потребовалось немного времени, чтобы понять это.

Dzmitry Lahoda
14 июля 2021 в 10:06
0

работает ли это для оконных контейнеров - похоже, нет.

Syed Muhammad Asad
3 сентября 2021 в 09:17
0

--network="host" в docker run решил мою проблему

Pavol Travnik
5 октября 2021 в 14:58
0

К сожалению, это работает только для Docker Desktop. Это сделано для целей разработки и не будет работать в производственной среде за пределами Docker Desktop для Mac.

avatar
Prince
4 февраля 2022 в 12:03
2

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

.

Посмотрите это - https://coderhelper.com/a/48547074/14120621

avatar
Yılmaz Durmaz
26 января 2022 в 21:15
5

Лет через 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-адрес не является статическим и требует настройки маршрутизации и брандмауэра.

avatar
Tires
25 мая 2021 в 19:00
1

Несмотря на множество длинных, непонятных ответов, короткий. Если ваша сеть моста докеров - 172.17.0.0/16, выполните следующие действия:

  1. Привяжите свой контейнер к 172.17.0.1, например. -p 172.17.0.1:8080:8080 (какой бы ни был шлюз в вашей сети моста Docker)
  2. Просто войдите в порт 172.17.0.1 8080, например. curl http://172.17.0.1:8080/ из другого контейнера
avatar
MichaelMoser
23 марта 2021 в 10:19
1

сервер на хосте прослушивает порт 5000; он отправит строку response from host обратно в качестве ответа

echo "response from host" | nc -l -p 5000

докер по умолчанию работает в режиме моста (это более безопасно, чем в режиме хост-сети); процесс в докере получает адрес ipv4 для первого сетевого интерфейса на хосте, отличного от 127.0.0.1; этот адрес ipv4 передается докеру через переменную окружения HOSTIP; внутри докера есть команда nc, которая подключается к серверу по ip хоста и порту 5000; команда также считывает ответ сервера.

HOST=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | awk '{ print $2 }' | head -1 | sed -n 's/[^0-9]*\([0-9\.]*\)/\1/p'); docker run -e HOSTIP="${HOST}" --rm -it alpine /bin/sh -c 'echo "greetings from container" | nc $HOSTIP 5000 -v'

Выражение, вычисляющее IPv4-адрес первого интерфейса в списке, действительно работает в OSX и Linux:

HOST=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | awk '{ print $2 }' | head -1 | sed -n 's/[^0-9]*\([0-9\.]*\)/\1/p')

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

docker run --expose 5000 -p :5000:5000 --rm -it alpine /bin/sh -c 'echo "response from host" | nc -l -p 5000'

- выставить 5000 контейнер докеров может принимать соединение через порт 5000

-p: 5000: 5000 механизм докеров на стороне хоста прослушивает порт 5000 на любом интерфейсе и перенаправляет соединения на порт 5000 в контейнерной сети (где работает nc).

avatar
balki
22 января 2021 в 21:39
4

Подключитесь к адресу шлюза.

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

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

[Unit]
After=docker.service

Пример

❯ python -m http.server &> /dev/null &
[1] 149976

❯ docker run --rm python python -c  "from urllib.request import urlopen;print(b'Directory listing for' in urlopen('http://172.17.0.1:8000').read())" 
True
avatar
Duc Trung Mai
30 ноября 2020 в 06:27
2

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

Amin Shojaei
25 апреля 2021 в 16:33
0

Работал у меня. Я использовал команду ifconfig и взял первый ip inet, и это кажется правильным

avatar
Ehsan88
21 ноября 2020 в 13:45
5

Сначала просмотрите этот ответ, чтобы узнать о вариантах решения этой проблемы. Но если вы используете 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
...
Ernestyno
18 декабря 2020 в 13:19
0

Ага. Он работает с: network_mode: host. Теперь может получить доступ к локальным доменным именам / etc / hosts, которые указывают на контейнеры докеров другого проекта.

avatar
DeyaEldeen
27 июля 2020 в 09:52
140

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

host.docker.internal

вместо

localhost

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

Jolta
8 октября 2020 в 11:21
12

Может быть, этот ответ можно было бы немного расширить и уточнить? Означает ли это, что вы все еще можете использовать режим моста?

Shane Cheek
23 марта 2021 в 23:54
9

@ArnoldRoa, это будет работать только на Mac / Windows, но не на Linux.

Triynko
26 апреля 2021 в 04:31
9

Не работает по состоянию на 26.04.2021. host.docker.internal ни к чему не приводит.

Kieran E
12 мая 2021 в 16:52
0

Невозможно воспроизвести проблему @ Triynko - у меня это отлично работает (движок: 20.10.6)

Brian Burns
25 мая 2021 в 04:43
1

Для настройки host.docker.internal с помощью docker-compose см. Coderhelper.com/a/67158212/243392

sjcoder
18 августа 2021 в 09:03
0

Спасибо, работает как шарм на Mac

Inigo
11 октября 2021 в 13:11
0

Запуск WSL2 в Windows 10 (рабочий стол Docker с включенным сервером WSL). Это не работает.

Rakesh Kumar Srivastava
28 октября 2021 в 09:23
0

Отлично. Это работает.

gdm
29 ноября 2021 в 09:30
0

root @ e8528aaeab39: / app # redis-cli -h "host.docker.internal" Не удалось подключиться к Redis на host.docker.internal: 6379: имя или служба неизвестны, не подключено>

avatar
L.T
15 июля 2020 в 01:25
0

если вы используете docker-compose, возможно, это сработает:

iptables -I INPUT ! -i eth0 -p tcp --dport 8001 -j ACCEPT

eth0 - это ваш сетевой интерфейс, который подключается к Интернету, а 8081 порт хост-сервера

лучший способ для правила iptables - iptables TRACE

avatar
wiseCoder
2 июля 2020 в 05:55
1

Чтобы все работало, вам нужно создать конфигурацию для вашего сервера (caddy, nginx), где основным доменом будет «docker.for.mac.localhost». Для этого замените в baseURL «http: // localhost / api» на «http: //docker.for.mac.localhost/api»

docker-compose.yml

backend:
  restart: always
  image: backend
  build:
    dockerfile: backend.Dockerfile
    context: .
  environment:
    # add django setting.py os.getenv("var") to bd config and ALLOWED_HOSTS CORS_ORIGIN_WHITELIST
    DJANGO_ALLOWED_PROTOCOL: http
    DJANGO_ALLOWED_HOSTS: docker.for.mac.localhost
    POSTGRES_PASSWORD: 123456
    POSTGRES_USER: user
    POSTGRES_DB: bd_name
    WAITDB: "1"
  volumes:
    - backend_static:/app/static
    - backend_media:/app/media
  depends_on:
    - db

frontend:
  restart: always
  build:
    dockerfile: frontend.Dockerfile
    context: .
  image: frontend
  environment:
    #  replace baseURL for axios
    API_URL: http://docker.for.mac.localhost/b/api
    API_URL_BROWSER: http://docker.for.mac.localhost/b/api
    NUXT_HOST: 0.0.0.0
  depends_on:
    - backend

caddy:
  image: abiosoft/caddy
  restart: always
  volumes:
    - $HOME/.caddy:/root/.caddy
    - ./Caddyfile.local:/etc/Caddyfile
    - backend_static:/static
    - backend_media:/media
  ports:
  - 80:80
  depends_on:
    - frontend
    - backend
    - db

Caddyfile.local

http://docker.for.mac.localhost {

  proxy /b backend:5000 {
    header_upstream Host {host}
    header_upstream X-Real-IP {remote}
    header_upstream X-Forwarded-For {remote}
    header_upstream X-Forwarded-Port {server_port}
    header_upstream X-Forwarded-Proto {scheme}
  }

  proxy / frontend:3000 {
    header_upstream Host {host}
    header_upstream X-Real-IP {remote}
    header_upstream X-Forwarded-For {remote}
    header_upstream X-Forwarded-Port {server_port}
    header_upstream X-Forwarded-Proto {scheme}
  }

  root /

  log stdout
  errors stdout
  gzip
}

http://docker.for.mac.localhost/static {
  root /static
}

http://docker.for.mac.localhost/media {
  root /media
}

django settings.py

ALLOWED_HOSTS = [os.getenv("DJANGO_ALLOWED_HOSTS")]
    
CORS_ORIGIN_WHITELIST = [f'{os.getenv("DJANGO_ALLOWED_PROTOCOL")}://{os.getenv("DJANGO_ALLOWED_HOSTS")}']

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql_psycopg2",
        "NAME": os.getenv("POSTGRES_DB"),
        "USER": os.getenv("POSTGRES_USER"),
        "PASSWORD": os.getenv("POSTGRES_PASSWORD"),
        "HOST": "db",
        "PORT": "5432",
    }
}

nuxt.config.js (переменная baseURL переопределит API_URL среды)

axios: {
  baseURL: 'http://127.0.0.1:8000/b/api'
},
avatar
Binh Ho
25 апреля 2020 в 05:26
6

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

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

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

Ray
29 ноября 2021 в 21:21
0

Это небольшая хитрость. Я не пробовал, но это довольно удобное быстрое решение

avatar
Praveenkumar Beedanal
7 февраля 2020 в 15:51
18

Для Windows,

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

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

A. Zalonis
19 апреля 2020 в 19:53
1

у меня не работает. У меня есть Mac, и я пытаюсь из контейнера php подключиться к localhost mysql. Любая идея ?

avatar
F. Kam
6 февраля 2020 в 04:00
0

Я делаю это так: я передаю IP-адрес хоста в качестве переменной среды в контейнер. Затем контейнер обращается к хосту с помощью этой переменной.

kmjb
17 февраля 2020 в 14:11
0

Вы можете проиллюстрировать, как вы это делаете? Я пробовал этот подход, но не добился большого успеха

F. Kam
20 февраля 2020 в 08:29
0

`docker run -i -t -e HOST = 10.145.2.123 ubuntu root @ ce2a843da3ee: / tmp # ./telnet $ HOST 22 Попытка 10.145.2.123 ... Подключено к 10.145.2.123. Экранирующий символ - '^]'. SSH-2.0-OpenSSH_7.4`

avatar
storenth
23 января 2020 в 12:45
5

Вам необходимо знать шлюз! Мое решение с локальным сервером заключалось в том, чтобы открыть его под 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

avatar
Leandro
27 сентября 2019 в 02:32
2

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

Ole S
22 апреля 2020 в 21:17
0

Это простейшее решение. Это сработало для меня, и я рекомендовал много

avatar
JShorthouse
7 сентября 2019 в 12:12
7

Для 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
arvindd
26 марта 2020 в 12:06
2

Это то же самое, что упомянул @ ray-d выше, но хорошо объяснено. Спасибо! Кроме того, при использовании docker-compose мне также пришлось добавить правило DNAT в цепочку PREROUTING для всех пакетов, поступающих также на интерфейс docker0: потому что docker-compose, похоже, использует docker0 во время сборки (как ни странно, но не во время запусков): sysctl -w net.ipv4.conf.docker0.route_localnet=1 и iptables -t nat -A PREROUTING -p tcp -i docker0 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025

avatar
Shirish Hirekodi
13 июля 2019 в 13:12
14

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

Оставим это здесь для других, кто может захотеть выполнять вызовы 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. «Сети»: должно быть «my-net»

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

Проверьте настройки сети для второго контейнера docker inspect second_container. «Сети»: должно быть my-net

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

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

Simar Singh
20 сентября 2019 в 18:04
0

Именно то, что я искал. Спасибо

Sly Gryphon
9 февраля 2021 в 01:01
0

Если вы знаете, что это не ответ на вопрос (а это не так, потому что вопрос конкретно касается localhost), почему вы его публикуете?

avatar
BMitch
30 июня 2019 в 15:28
20

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

  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 route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')" ...

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

Немного менее портативным является использование host.docker.internal. Это работает в текущих версиях Docker для Windows и Docker для Mac. А в 20.10 эта возможность была добавлена ​​в Docker для Linux, когда вы передаете специальную запись хоста с:

docker run --add-host host.docker.internal:host-gateway ...

host-gateway - это специальное значение, добавленное в Docker 20.10, которое автоматически расширяется до IP-адреса хоста. Подробнее см. в этом PR.

Вариант 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 преобразует в использование сокета.

MichaelMoser
23 марта 2021 в 07:26
0

для option2 (единственное, что сработало из всех ответов): следующая команда получает IP-адрес интерфейса, отличного от локального хоста, как на osx, так и на linux: ifconfig | grep 'inet ' | grep -v 127.0.0.1 | awk '{ print $2 }' | head -1 | sed -n 's/[^0-9]*\([0-9\.]*\)/\1/p'

sanmai
26 мая 2021 в 03:11
0

--add-host host.docker.internal:host-gateway золотой

avatar
patryk.beza
22 марта 2019 в 14:10
1

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

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

(как предлагает @Mahoney здесь).

avatar
Felipe Toledo
22 марта 2019 в 02:40
22

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

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

HyukHyukBoi
28 января 2020 в 17:31
0

В HaProxy это решение по какой-то причине перестало работать с acl, работает только настройка по умолчанию.

avatar
Elad
9 ноября 2018 в 22:23
16

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

TheManish
27 марта 2019 в 14:25
2

Оно работает. Даже не нужно указывать --network = host. похоже, что 10.0.2.2 установлен в качестве IP-адреса по умолчанию для хоста. Спасибо.

151291
31 марта 2020 в 05:04
1

Но могу ли я использовать этот статический IP-адрес для всех версий Windows и Mac? как я могу справиться с этим для нескольких платформ с помощью скрипта?

Kihats
2 мая 2020 в 12:55
0

Это сработало для меня. Просто запустите ipconfig на своем хосте (Windows) и получите IP-адрес под Ethernet adapter vEthernet (DockerNAT)

avatar
qoomon
17 октября 2018 в 15:08
40

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

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

KMC
17 сентября 2019 в 12:57
11

Я могу подтвердить, что это не работает в Docker для Windows 19.03.2 с контейнером Windows.

qoomon
18 сентября 2019 в 05:12
0

есть идеи, как это исправить? (Я не пользователь Windows)

KMC
18 сентября 2019 в 12:26
0

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

Triynko
26 апреля 2021 в 04:32
1

Я могу подтвердить, что это НЕ РАБОТАЕТ в Docker для Windows версии 20.10.5. Это бесит. IP-адрес хоста (из контейнера) меняется случайным образом. Как, черт возьми, я должен развернуть строку подключения, когда IP-адрес хоста изменяется во время выполнения, а host.docker.internal ничего не разрешает?

qoomon
27 апреля 2021 в 06:12
0

@Triynko как вы определяете ip хоста на данный момент?

qoomon
27 апреля 2021 в 06:24
1

@Triynko, можете ли вы выполнить следующие команды и сообщить мне, удастся ли что-нибудь из них? docker run --rm alpine ping host.docker.internal docker run --rm alpine ping docker.for.win.localhost docker run --rm alpine ping gateway.docker.internal

avatar
Lokesh S
17 сентября 2018 в 15:18
0

Для Windows Machine: -

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

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

enter image description here

enter image description here

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

localhost:32768 

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

einjohn
9 мая 2019 в 13:24
7

Хотя этот ответ может предоставить полезную информацию для некоторых пользователей, это неправильный путь вокруг ! Речь идет о доступе к службе , работающей в контейнере , с хост-машины. Однако вопрос касался доступа к службе , запущенной на хосте , из контейнера.

avatar
hasnat
11 июня 2018 в 08:47
3

Вы можете получить IP-адрес хоста с помощью образа alpine

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
avatar
Ralph Willgoss
9 ноября 2017 в 10:49
21

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

avatar
Ray D
27 сентября 2017 в 13:22
40

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

Хорошо, ваш сервер localhost имеет интерфейс докеров по умолчанию docker0 с 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 ).

Patrick
12 сентября 2019 в 14:34
4

Какова цель второй команды iptable? Я понимаю, что первый - это переписать все назначения tcp, соответствующие 172.17.0.1:3306, на 127.0.0.1:3306, но зачем нужна вторая команда iptable?

tuna
27 апреля 2021 в 20:58
0

Это сделало мой день! Спасибо, что поделились

avatar
mohan08p
6 сентября 2017 в 12:05
2

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

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

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

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

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

$ docker run -it alpine ifconfig

При изменении пространства имен на host, сети 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 на хосте, запустить и отладить свое приложение. Но идти этим путем не рекомендуется. Надеюсь, поможет.

avatar
sopheamak
17 июля 2017 в 07:47
4

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

  • установить публичный доступ к локальному серверу 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

    #!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'
    
    

    services:
    tomcatwar: extra_hosts: - "local:10.1.2.232" image: sopheamak/springboot_docker_mysql
    ports: - 8080:8080 environment: - DATABASE_HOST=local - DATABASE_USER=root - DATABASE_PASSWORD=root - DATABASE_NAME=demo - DATABASE_PORT=3306

avatar
dansalmo
17 мая 2017 в 18:15
16

Простейшее решение для 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

Matt
23 марта 2018 в 03:02
3

Docker для Mac теперь предоставляет имя хоста docker.for.mac.host.internal.

avatar
Janne Annala
21 апреля 2017 в 11:33
445

Для macOS и Windows

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

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

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

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

Docker для Mac версий 17.12–18.02

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

Docker для Mac версий 17.06 - 17.11

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

Docker для 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

Richard Frank
22 июля 2017 в 05:46
7

блестяще и спасибо, это сработало для меня изнутри контейнера. mysql -uroot -hdocker.for.mac.localhost

99Sono
3 декабря 2017 в 15:06
2

docker.for.mac.localhost Это именно то, что я искал. Но в то же время это чертовски грязно. В docker можно было бы ожидать, что хук docker.for.mac.localhost будет общим внутренним именем докера, которое будет действительным для любой операционной системы, а не только для Mac. Но для целей разработки этого достаточно.

Jya
19 февраля 2018 в 13:46
1

DNS-имя docker.for.mac.host.internal следует использовать вместо docker.for.mac.localhost (все еще действующее) для разрешения хоста из контейнеров, поскольку существует RFC, запрещающий использование поддоменов localhost. См. tools.ietf.org/html/draft-west-let-localhost-be-localhost-06.

Jorge Orpinel Pérez
11 марта 2018 в 01:18
0

У меня это не работает. Когда я docker run -e HOSTNAME= docker.for.mac.host.internal , контейнер создается, но ничего не происходит. Мне нужно тогда crtl + C. По крайней мере, с --net=host -e HOSTNAME=localhost контейнер работает и жалуется, что не может найти нужную мне службу (MySQL db).

iedmrc
18 сентября 2020 в 07:47
0

Так быстро и полезно. Спасибо!

quento
28 октября 2020 в 15:48
0

большое спасибо, поле docker.for.mac.host.internal работает для macOs

avatar
sivabudh
7 февраля 2017 в 07:15
11

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


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

Сетевой режим хоста не работает на Mac. Вы должны использовать псевдоним IP, см. Https://coderhelper.com/a/43541681/2713729

Что такое сетевой режим хоста? См .: 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.

sivabudh
7 февраля 2017 в 08:21
1

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

Xavier Huppé
24 февраля 2017 в 17:13
2

Очень хороший момент. Хотя возможно подключение из контейнера к службе хоста с неиспользуемым IP-подключением docs.docker.com/docker-for-mac/networking. Решение не из приятных ... но работает.

Mchl
22 мая 2017 в 10:39
0

Здесь хорошие вещи. Оказавшись внутри контейнера с --network="host", как, например, подключиться к хосту mysql?

sivabudh
22 мая 2017 в 11:00
1

@Buccleuch Просто используйте localhost. Посмотрите мой исходный код на GitHub: github.com/sivabudh/system-in-a-box/blob/master/dj_host_docker/…. Найдите 'HOST', вы увидите 127.0.0.1 для подключения к Postgresql.

Mchl
22 мая 2017 в 11:07
0

Я смог получить доступ к базам данных хоста mysql, установив том в соответствии с @ user833482, и, конечно же, после установки mysql-client и server в контейнер докеров.

avatar
Casey
10 декабря 2016 в 15:53
13

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

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

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

Michael
3 августа 2017 в 23:08
4

Вы заслужили медаль! Я работал над этим два полных дня. Спасибо за помощь!

Contango
2 ноября 2017 в 15:44
1

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

avatar
Mariano Ruiz
3 августа 2016 в 21:30
110

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

enderland
15 марта 2017 в 15:51
1

В зависимости от вашего варианта использования вы можете даже просто уйти от использования здесь значения DOCKERHOST вместо «localhost» или 0.0.0.0 в любой службе, к которой ваш док-контейнер должен подключаться локально.

dieresys
26 апреля 2017 в 17:09
4

Я немного изменил ваше решение, чтобы оно было совместимо с пользовательскими сетями: export DOCKERHOST=$(docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' <NETWORK-NAME> | awk -F "/" 'NR==1{print $1}') где <NETWORK-NAME> может быть мостом или именем сети, как определено docker-compose ( обычно путь-имя - имя_сети ).

Justin
30 июня 2017 в 11:12
1

Вам нужно добавить комментарий: используйте dockerhost в качестве хоста для подключения к базе данных (обычно заменяйте на localhost в файле конфигурации).

Eddie
16 декабря 2019 в 11:08
0

странное решение, но это единственное, что заставляет xdebug работать под докером с php cli

HyukHyukBoi
28 января 2020 в 18:27
0

После этого решения в haproxy перестал работать Acl. Есть идеи, почему?

avatar
user833482
27 мая 2015 в 13:36
50

Это сработало для меня в стеке 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
user1226868
6 июня 2015 в 14:45
2

Это гораздо более чистое решение, которое не раскрывает Mysql извне (если не используется брандмауэр).

Joel E Salas
19 января 2016 в 21:54
5

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

Private
13 октября 2016 в 09:21
6

@JoelESalas У вас есть источник для этого утверждения?

Private
13 октября 2016 в 10:32
0

Я обнаружил, что это самое простое решение. Недурно user833482! Вам следует чаще вносить свой вклад в StackOverflow.

M Conrad
11 января 2017 в 01:28
4

@JoelESalas Я думаю, вы ошибаетесь. Клиентская библиотека mysql даже по умолчанию использует сокеты unix при подключении к localhost, а не фактически устанавливает соединение с localhost. Сокет unix позволяет избежать накладных расходов на стек TCP и маршрутизацию и должен работать быстрее.

Maksym
5 декабря 2020 в 17:30
0

Это решение в конечном итоге сработало для моего варианта использования подключения logstash, работающего в контейнере, к MariaDB, работающему на моем хосте, с использованием JDBC. Однако есть одна загвоздка: вы должны включить зависимость от JNA. Оставив это как навигационную крошку для других: coderhelper.com/questions/25918416/…

avatar
orzel
12 марта 2015 в 23:31
8

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

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

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

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

«Почему бы также не привязать mysql к docker0?»

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

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

Thomasleveil
13 марта 2015 в 23:31
4

с хоста докера вы все еще можете подключиться к серверу MySQL, используя адрес 172.17.42.1. Но в остальном ваша заметка верна. Кроме того, я отредактировал свой ответ с помощью сетевого режима host, который позволяет удерживать сервер MySQL привязанным к 127.0.0.1, позволяя контейнерам подключаться к нему.

orzel
14 марта 2015 в 04:19
0

нет, как я уже сказал, вы не можете подключиться к 172.17.42.1, если mysql привязан к localhost.

0x89
9 марта 2016 в 16:00
5

«Привязка mysql к 172.17.42.1 не позволит другим программам использовать базу данных на хосте для доступа к нему». - это неправда. Другие программы могут использовать mysql, им просто нужно подключиться к 172.17.42.1 вместо localhost / 127.0.0.1.

halfer
16 июня 2017 в 15:05
0

Решение проблемы в этом ответе обычно состоит в том, чтобы заставить сервер MySQL привязаться к 0.0.0.0, а затем настроить брандмауэр, чтобы база данных была недоступна из Интернета.