如何从Docker容器内部连接到机器的本地主机?

2024-05-23 15:06:23 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我有一个运行在docker容器中的Nginx,我有一个运行在localhost上的mysql,我想从Nginx中连接到mysql。MySql在localhost上运行,并且没有向外界公开端口,因此它绑定在localhost上,而不是绑定在机器的ip地址上

是否有任何方法可以从docker容器中连接到此MySql或localhost上的任何其他程序

这个问题与“如何从docker容器中获取docker主机的IP地址”不同,因为docker主机的IP地址可能是网络中的公共IP或私有IP,而这些IP可能在docker容器中可以访问,也可能无法访问(我指的是公共IP,如果托管在AWS或其他地方)。即使您拥有docker主机的IP地址,但这并不意味着您可以从容器内连接到docker主机,因为docker网络可能是覆盖、主机、网桥、MAVLAN、无等,这限制了该IP地址的可访问性


Tags: 方法端口docker程序ip网络机器localhost
3条回答

编辑:

如果您使用的是Docker-for-macDocker-for-Windows18.03+,只需使用主机host.docker.internal(而不是连接字符串中的127.0.0.1)连接到mysql服务即可

如果您正在使用Docker for Linux 20.10.0+,那么如果您使用--add-host host.docker.internal:host-gateway选项启动Docker容器,也可以使用主机host.docker.internal

否则,请阅读下面的内容


TLDR

docker run命令中使用--network="host",然后docker容器中的127.0.0.1将指向docker主机

注意:此模式仅适用于Docker for Linux,per the documentation


关于docker容器网络模式的说明

Docker在运行容器时提供different networking modes。根据您选择的模式,您将以不同的方式连接到docker主机上运行的MySQL数据库

docker运行--network=“bridge”(默认)

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主机在docker0网络接口上有IP地址172.17.42.1

现在启动一个新容器并在其上获取一个shell: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主机172.17.42.1的IP地址被设置为默认路由,并且可以从您的容器访问

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运行--network=“host”

或者,您可以使用network settings set to ^{}运行docker容器。这样的容器将与docker主机共享网络堆栈,并且从容器的角度来看,localhost(或127.0.0.1)将引用docker主机

请注意,docker容器中打开的任何端口都将在docker主机上打开。这不需要^{} or ^{} ^{} option

我的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地址


从容器连接到MySQL

桥接模式

要以网桥模式从容器访问docker主机上运行的MySQL,需要确保MySQL服务正在侦听172.17.42.1IP地址上的连接

为此,请确保MySQL配置文件(my.cnf)中有bind-address = 172.17.42.1bind-address = 0.0.0.0

如果需要使用网关的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的连接。在docker主机上运行的要连接到MySQL的进程必须使用172.17.42.1IP地址

主机模式

要以主机模式从容器访问docker主机上运行的MySQL,可以在MySQL配置中保留bind-address = 127.0.0.1,只需从容器连接到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套接字进行连接

适用于macOS和Windows

Docker v 18.03及以上(自2018年3月21日起)

使用内部IP地址或连接到特殊DNS名称host.docker.internal,该名称将解析为主机使用的内部IP地址

Linux支持挂起https://github.com/docker/for-linux/issues/264

使用Docker早期版本的MacOS

Mac v 17.12至v 18.02的Docker

同上,但改用docker.for.mac.host.internal

Mac v 17.06至v 17.11的Docker

同上,但改用docker.for.mac.localhost

Mac 17.05及以下版本的Docker

要从docker容器访问主机,必须将IP别名附加到网络接口。您可以绑定任何您想要的IP,只要确保您没有将其用于任何其他内容

sudo ifconfig lo0 alias 123.123.123.123/24

然后确保您的服务器正在侦听上述IP或0.0.0.0。如果它正在本地主机127.0.0.1上侦听,它将不接受连接

然后只需将docker容器指向该IP,就可以访问主机了

要进行测试,可以在容器内运行类似curl -X GET 123.123.123.123:3000的程序

别名将在每次重新启动时重置,因此在必要时创建启动脚本

这里有解决方案和更多文档:https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

使用

host.docker.internal

而不是

localhost

完美地为我工作。👍

相关问题 更多 >