Доступ к базе данных хоста из контейнера докеров

132

Если у меня есть база данных mysql, запущенная на каком-то хост-компьютере, и на этом хосте также работает контейнер докеров: как мне получить доступ к базе данных mysql из контейнера докеров, который работает на хосте?

Например, есть ли способ опубликовать порт хостов в контейнере (обратный тому, что делает docker run -p)?

Райан Андерсон
источник
1
Если сервер MySQL прослушивает порт, не может ли контейнер просто подключиться к хосту на этом порту, как любое другое подключение к Интернету?
jwodder

Ответы:

87

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

В любом случае вы многие захотите попробовать использовать параметр --add-host для docker run, чтобы добавить IP-адрес хоста в файл / etc / host контейнера. Отсюда легко подключиться к хосту через любой требуемый порт:

Добавление записей в файл хостов контейнера

Вы можете добавить другие хосты в файл контейнера / etc / hosts, используя один или несколько флагов --add-host. В этом примере добавляется статический адрес для хоста с именем docker:

 $ docker run --add-host=docker:10.180.0.1 --rm -it debian
    $$ ping docker
    PING docker (10.180.0.1): 48 data bytes
    56 bytes from 10.180.0.1: icmp_seq=0 ttl=254 time=7.600 ms
    56 bytes from 10.180.0.1: icmp_seq=1 ttl=254 time=30.705 ms
    ^C--- docker ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
    round-trip min/avg/max/stddev = 7.600/19.152/30.705/11.553 ms

Примечание. Иногда вам нужно подключиться к хосту Docker, что означает получение IP-адреса хоста. Вы можете использовать следующие команды оболочки, чтобы упростить этот процесс:

 $ alias hostip="ip route show 0.0.0.0/0 | grep -Eo 'via \S+' | awk '{ print $2 }'"
 $ docker run  --add-host=docker:$(hostip) --rm -it debian

Документация:

https://docs.docker.com/engine/reference/commandline/run/

Обсуждения доступа к хосту из контейнера:

https://github.com/docker/docker/issues/1143

https://github.com/docker/docker/issues/10023

Джон Петроне
источник
Будет ли он также работать за обратным прокси-сервером NGINX?
kta
89

Из документов 18.03:

Я хочу подключиться из контейнера к службе на хосте

У хоста меняющийся IP-адрес (или его нет, если у вас нет доступа к сети). Начиная с 18.03, мы рекомендуем подключаться к специальному DNS-имени host.docker.internal, которое разрешается во внутренний IP-адрес, используемый хостом.

Шлюз также доступен как gateway.docker.internal.

ПРИМЕР: Вот что я использую для строки подключения MySQL внутри моего контейнера для доступа к экземпляру MySQL на моем хосте:

mysql://host.docker.internal:3306/my_awesome_database
Кевин Чен
источник
31
Просто подсказка: пока это работает только для Mac и Win
flp
ты спас мне день :)
amjad
4
Upvote. Не только из-за ответа, а потому, что вы должны КАК использовать его с примером.
granadaCoder
1
Я почти потратил на это 2 часа, большое спасибо.
Ашиш Байнаде
По-прежнему нет поддержки linux, как писал @flp, для тех, кому интересно. Вот проблема с github .
Галтелино
34

Начиная с Docker 17.06 и далее в контейнерах докеров доступно специальное DNS-имя только для Mac, которое разрешается в IP-адрес хоста. Это:

docker.for.mac.localhost

Документация находится здесь: https://docs.docker.com/docker-for-mac/networking/#httphttps-proxy-support

Bazmatiq
источник
3
docker.for.mac.host.internalначиная с этого Docker 17.12.0 ceмомента. docs.docker.com/docker-for-mac/release-notes/…
Zangetsu
docker.for.mac.localhost работает18.03.1-ce-mac65
cdignam
24

Используйте host.docker.internal начиная с Docker 18.03.

Игорь Де Оливейра Са
источник
2
как ? вы можете привести пример, как это использовать?
danfromisrael
Почему бы вам не запустить dockerized mysql?
Игорь Де Оливейра Са
не работает у меня наDocker version 18.03.0-ce, build 0520e24
scythargon
@ IgorDeOliveiraSá представьте следующий сценарий: в среде разработки у вас есть база данных, которая слушает 127.0.0.1:3306 в производственной среде, у вас есть база данных, которая прослушивает 127.0.0.1:3306, локально это локальная база данных, производство это прокси в облако, вам нужно либо dockerise mysql локально и для производства найдите другое решение, или вы можете просто подключиться от докера к порту, он будет работать в обоих случаях
Drachenfels
1
docker.for.mac.localhost у меня работает18.03.1-ce-mac65
cdignam
21

Другие ответы мне не подошли. Мой контейнер не смог разрешить IP- адрес хоста с помощью host.docker.internal . Есть два пути

  1. Совместное использование хост-сети --net = host:

    docker run -it --net=host  myimage
    
  2. Используя IP-адрес докера, обычно это 172.17.0.1 . Вы можете проверить это, вызвав команду ifconfig и взяв inet addr интерфейса докера.

    user@ubuntu:~$ ifconfig
    docker0   Link encap:Ethernet  HWaddr 02:42:a4:a2:b2:f1  
      inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
      inet6 addr: fe80::42:a4ff:fea2:b2f1/64 Scope:Link
    

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

  docker run -it -v /host_dir/docker_jdbc_config:${jetty_base}/var/config myimage

ПРИМЕЧАНИЕ. Ваша база данных может не разрешать внешние подключения. В случае postgresql вам нужно отредактировать 2 файла, как описано здесь и здесь :

  1. Отредактируйте postgresql.conf, чтобы прослушивать все адреса. По умолчанию он будет указывать на localhost.

    listen_addresses = '*'
    
  2. Отредактируйте pg_hba.conf, чтобы разрешить соединения со всех адресов. Добавьте в последнюю строку:

    host     all             all             0.0.0.0/0               md5
    

ВАЖНО: Последний шаг обновления доступа к базе данных не рекомендуется для производственного использования, если вы действительно не уверены, что делаете.

gmode
источник
--net = host работал у меня в среде CI, большое спасибо!
Samy