所以我有一个Nginx在docker容器中运行,我有一个mysql在本地主机上运行,我想从我的Nginx内部连接到MySql。MySql在localhost上运行,并且没有将端口暴露给外界,因此它绑定在localhost上,而不绑定在计算机的ip地址上。
有什么方法可以从此Docker容器中连接到此MySql或localhost上的任何其他程序吗?
该问题与“如何从Docker容器内部获取Docker主机的IP地址”不同,这是因为Docker主机的IP地址可以是网络中的公共IP或私有IP,这可能是也可能是无法从docker容器中访问(我的意思是如果托管在AWS或其他地方,则为公共IP)。即使你具有Docker主机的IP地址,也并不意味着你可以从容器内部连接到Docker主机,因为该IP地址可能会覆盖你的Docker网络,主机,网桥,macvlan,无其他网络,从而限制了Docker的可访问性该IP地址。
编辑:
如果你使用的是Docker-for-mac或Docker-for-Windows 18.03+,则只需使用主机host.docker.internal
(而不是127.0.0.1
连接字符串中的)连接到mysql服务。
如果你使用的 docker ,对Linux的20.10.0+,你也可以使用主机host.docker.internal
,如果你与你的开始多克尔容器--add-host host.docker.internal:host-gateway
选项。
否则,请阅读以下内容
--network="host"
在docker run
命令中使用,然后127.0.0.1
在Docker容器中将指向你的Docker主机。
注意:根据文档,此模式仅适用于Linux的Docker 。
Docker在运行容器时提供了不同的联网模式。根据你选择的模式,你将以不同的方式连接到在docker主机上运行的MySQL数据库。
Docker创建一个docker0
默认命名的网桥。docker主机和docker容器在该网桥上都有一个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
因此,在这里,我的Docker主机172.17.42.1
在docker0
网络接口上具有IP地址。
现在启动一个新容器并在其上安装一个外壳: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
因此,将Docker主机的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
或者,你可以运行将网络设置设置为host
的Docker容器。这样的容器将与docker主机共享网络堆栈,并且从容器的角度来看,localhost
(或127.0.0.1
)将引用docker主机。
请注意,你在Docker容器中打开的任何端口都将在Docker主机上打开。而且这不需要-p
or-P
docker run
选项。
我的Docker主机上的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
并在主机模式下从Docker容器中获取:
[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
如你所见,docker主机和docker容器共享完全相同的网络接口,因此具有相同的IP地址。
要以桥接模式从容器访问在docker主机上运行的MySQL ,你需要确保MySQL服务正在侦听172.17.42.1
IP地址上的连接。
要做到这一点,请确保你有两种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服务器,它将监听所有网络接口上的连接。这意味着你可以从Internet上访问MySQL服务器;确保相应地设置防火墙规则。
注意2:如果你使用bind-address = 172.17.42.1
的是MySQL服务器,则不会监听与的连接127.0.0.1
。在要连接到MySQL的docker主机上运行的进程必须使用172.17.42.1
IP地址。
要以主机模式从容器访问在docker主机上运行的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套接字进行连接。
谢谢您这么详细的回答!根据我的收集,使用主机模式是通过localhost获得此功能的唯一方法。我还没有尝试过,但是我认为您可以创建一个单独的网络来通过它们自己的网桥连接容器,从而为它们提供一个通用的“本地主机”。
OSX用户注意事项:首先使用“ docker-machine ssh default”登录到您的docker虚拟机(boot2docker),然后运行“ sudo ip addr show docker0”。从那里继续执行Thomas的指示。
我正在为Mac运行Docker,并且不再有172.17.42.1,也不再有docker0。网关是172.17.0.1,甚至无法
telnet 172.17.0.1 3306
您可以将mysql套接字安装到容器中,而不是像
-v /var/run/mysqld/mysqld.sock:/tmp/mysql.sock
这样进行联网。当您在Mac上运行Docker而不使用boot2docker时,如果没有docker0接口,有人可以解决这种情况吗?