Acessar banco de dados do host a partir de um contêiner de docker

131

Se eu tiver um banco de dados mysql em execução em alguma máquina host, e esse host também estiver executando um contêiner de docker: como acessar o banco de dados mysql a partir do contêiner de docker que está sendo executado no host?

Por exemplo, existe uma maneira de publicar uma porta de hosts no contêiner (o inverso do que o docker executa -p)?

Ryan Anderson
fonte
1
Se o servidor MySQL estiver escutando uma porta, o contêiner não pode simplesmente se conectar ao host nessa porta como qualquer outra conexão com a Internet?
jwodder

Respostas:

87

Existem várias discussões de longa data sobre como fazer isso de maneira consistente, bem compreendida e portátil. Nenhuma resolução completa, mas eu irei vinculá-lo às discussões abaixo.

De qualquer forma, muitos desejam tentar usar a opção --add-host para executar o docker para adicionar o endereço IP do host ao arquivo / etc / host do contêiner. A partir daí, é trivial conectar-se ao host em qualquer porta necessária:

Adicionando entradas a um arquivo de hosts de contêiner

Você pode adicionar outros hosts ao arquivo / etc / hosts de um contêiner usando um ou mais sinalizadores --add-host. Este exemplo adiciona um endereço estático para um host chamado 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

Nota: Às vezes, você precisa se conectar ao host do Docker, o que significa obter o endereço IP do host. Você pode usar os seguintes comandos do shell para simplificar esse processo:

 $ 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

Documentação:

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

Discussões sobre como acessar o host do contêiner:

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

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

John Petrone
fonte
Ele também estará trabalhando por trás de um proxy reverso NGINX?
kta 9/06
89

Dos documentos 18.03:

Quero conectar-me de um contêiner a um serviço no host

O host tem um endereço IP alterado (ou nenhum, se você não tiver acesso à rede). A partir de 18.03, nossa recomendação é conectar-se ao nome DNS especial host.docker.internal, que resolve o endereço IP interno usado pelo host.

O gateway também é acessível como gateway.docker.internal.

EXEMPLO: Aqui está o que eu uso para minha cadeia de conexão MySQL dentro do meu contêiner para acessar a instância do MySQL no meu host:

mysql://host.docker.internal:3306/my_awesome_database
Kevin Chen
fonte
31
Assim como dica: isso só funciona para Mac e Win até agora
flp
você salvou o meu dia :)
Amjad
4
Voto a favor. Não apenas por causa da resposta, mas porque você deve COMO usá-lo com um exemplo.
usar o seguinte código
Eu quase passei duas horas para conseguir isso, muito obrigado.
Ashish Bainade 28/08/19
Ainda não há suporte ao linux como o @flp escreveu, para os curiosos. Aqui está a questão do github .
GAltelino 24/04
34

A partir do Docker 17.06, um nome DNS especial somente para Mac está disponível nos contêineres do docker que são resolvidos para o endereço IP do host. Isto é:

docker.for.mac.localhost

A documentação está aqui: https://docs.docker.com/docker-for-mac/networking/#httphttps-proxy-support

Bazmatiq
fonte
3
docker.for.mac.host.internala partir Docker 17.12.0 cede docs.docker.com/docker-for-mac/release-notes/…
Zangetsu
docker.for.mac.localhost trabalha em18.03.1-ce-mac65
cdignam 12/07/2018
24

Use host.docker.internal a partir do Docker 18.03.

Igor De Oliveira Sá
fonte
2
como ? você pode dar um exemplo de como usá-lo?
Danfromisrael #
Por que você não executa um mysql dockerized?
Igor De Oliveira Sá
não funciona para mim noDocker version 18.03.0-ce, build 0520e24
scythargon
@ IgorDeOliveiraSá imagine o seguinte cenário: no ambiente de desenvolvimento, você tem algum banco de dados que escuta 127.0.0.1:3306 no ambiente de produção, você tem um banco de dados escutando 127.0.0.1:3306, localmente é db local, produção é proxy para a nuvem, você deve dockerise mysql localmente e e para a produção de encontrar outra solução, ou você pode simplesmente ligar a partir de janela de encaixe para a porta, ele vai trabalhar para ambos os casos
Drachenfels
1
docker.for.mac.localhost funciona para mim em18.03.1-ce-mac65
cdignam
21

Outras respostas não funcionaram bem para mim. Meu contêiner não pôde resolver o IP do host usando host.docker.internal . Existem duas maneiras

  1. Compartilhando a rede do host --net = host:

    docker run -it --net=host  myimage
    
  2. Usando o endereço IP do docker, que geralmente é 172.17.0.1 . Você pode verificá-lo chamando o comando ifconfig e pegando inet addr da interface do docker

    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
    

Depois de ter esse endereço IP, você pode passá-lo como um argumento para executar o docker e depois para o aplicativo ou, como eu faço, mapear o local do jdbc.properties via volume para o diretório na máquina host, para que você possa gerenciar o arquivo externamente .

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

NOTA: Seu banco de dados pode não permitir conexões externas. No caso do postgresql, você precisa editar 2 arquivos, conforme descrito aqui e aqui :

  1. Edite o postgresql.conf para ouvir em todos os endereços. Por padrão, ele apontará para localhost.

    listen_addresses = '*'
    
  2. Edite pg_hba.conf para permitir conexões de todos os endereços. Adicione na última linha:

    host     all             all             0.0.0.0/0               md5
    

IMPORTANTE: A última etapa da atualização do acesso ao banco de dados não é recomendada para uso em produção, a menos que você tenha certeza do que está fazendo.

gmode
fonte
--net = host trabalhou para mim em um ambiente de CI, muito obrigado!
Samy