Edit: Se você estiver usando o Docker-for-mac ou o Docker-for-Windows 18.03+, conecte-se ao seu serviço mysql usando o host host.docker.internal
(em vez da 127.0.0.1
string de conexão).
A partir do Docker 18.09.3, isso não funciona no Docker para Linux. Uma correção foi enviada em 8 de março de 2019 e, esperamos, será mesclada à base de código. Até então, uma solução alternativa é usar um contêiner conforme descrito na resposta do qoomon .
2020-01: foram feitos alguns progressos . Se tudo correr bem, isso deve ocorrer no Docker 20.04
TLDR
Use --network="host"
em seu docker run
comando e, 127.0.0.1
em seguida, em seu contêiner de docker apontará para o host do docker.
Nota: Este modo funciona apenas no Docker for Linux, de acordo com a documentação .
Nota sobre os modos de rede do contêiner do docker
O Docker oferece diferentes modos de rede ao executar contêineres. Dependendo do modo escolhido, você se conectaria ao banco de dados MySQL em execução no host do docker de maneira diferente.
docker run --network = "bridge" (padrão)
O Docker cria uma ponte denominada docker0
por padrão. O host da docker e os contêineres têm um endereço IP nessa ponte.
no host do Docker, digite que sudo ip addr show docker0
você terá uma saída semelhante a:
[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
Portanto, aqui meu host docker tem o endereço IP 172.17.42.1
na docker0
interface de rede.
Agora inicie um novo contêiner e obtenha um shell: docker run --rm -it ubuntu:trusty bash
e dentro do tipo de contêiner ip addr show eth0
para descobrir como sua interface de rede principal está configurada:
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
Aqui meu contêiner tem o endereço IP 172.17.1.192
. Agora veja a tabela de roteamento:
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
Portanto, o endereço IP do host da janela de encaixe 172.17.42.1
é definido como a rota padrão e é acessível a partir do seu contêiner.
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"
Como alternativa, você pode executar um contêiner de docker com as configurações de rede definidas comohost
. Esse contêiner compartilhará a pilha de rede com o host do docker e, do ponto de vista do container, localhost
(ou 127.0.0.1
) fará referência ao host do docker.
Esteja ciente de que qualquer porta aberta no contêiner do docker seria aberta no host do docker. E isso sem exigir a opção -p
ou-P
docker run
.
Configuração de IP no meu host docker:
[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
e de um contêiner de docker no modo host :
[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
Como você pode ver, o host e o contêiner de docker compartilham exatamente a mesma interface de rede e, como tal, têm o mesmo endereço IP.
Conectando ao MySQL a partir de contêineres
Modo Ponte
Para acessar o MySQL em execução no host docker a partir de contêineres no modo bridge , é necessário garantir que o serviço MySQL esteja escutando as conexões no 172.17.42.1
endereço IP.
Para fazer isso, verifique se você possui bind-address = 172.17.42.1
ou está bind-address = 0.0.0.0
no seu arquivo de configuração do MySQL (my.cnf).
Se você precisar definir uma variável de ambiente com o endereço IP do gateway, poderá executar o seguinte código em um contêiner:
export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')
depois, no seu aplicativo, use a DOCKER_HOST_IP
variável de ambiente para abrir a conexão com o MySQL.
Nota: se você usar bind-address = 0.0.0.0
o servidor MySQL, escutará as conexões em todas as interfaces de rede. Isso significa que seu servidor MySQL pode ser acessado da Internet; certifique-se de configurar as regras do firewall de acordo.
Nota 2: se você usar bind-address = 172.17.42.1
o servidor MySQL, não ouvirá as conexões feitas 127.0.0.1
. Os processos em execução no host do docker que desejariam se conectar ao MySQL precisariam usar o 172.17.42.1
endereço IP.
modo host
Para acessar o MySQL em execução no host docker a partir de contêineres no modo host , você pode manter bind-address = 127.0.0.1
sua configuração do MySQL e tudo que você precisa fazer é conectar-se a 127.0.0.1
partir de seus contêineres:
[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>
nota: use mysql -h 127.0.0.1
e não mysql -h localhost
; caso contrário, o cliente MySQL tentaria se conectar usando um soquete unix.