一尘不染

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

javascript

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

有没有办法从这个 docker 容器中连接到这个 MySql 或本地主机上的任何其他程序?

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


阅读 251

收藏
2022-02-08

共1个答案

一尘不染

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

如果您使用的是 Docker-for-Linux 20.10.0+,host.docker.internal 如果--add-host host.docker.internal:host-gateway您使用该选项启动 Docker 容器,您也可以使用主机。

否则,请阅读下文


TLDR

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

注意:根据文档,此模式仅适用于 Docker for Linux 。


docker 容器网络模式注意事项

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

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

现在启动一个新容器并在其上获取一个 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 主机的 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

搬运工运行–network =“主机”

或者,您可以运行一个将网络设置设置为host. 这样的容器将与 docker 主机共享网络堆栈,从容器的角度来看,localhost(或127.0.0.1)将引用 docker 主机。

请注意,在您的 docker 容器中打开的任何端口都将在 docker 主机上打开。这不需要-por-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 地址。


从容器连接到 MySQL

桥接模式

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

为此,请确保您的 MySQL 配置文件 (my.cnf) 中有一个bind-address = 172.17.42.1或其中一个。bind-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.0MySQL 服务器将侦听所有网络接口上的连接。这意味着可以从 Internet 访问您的 MySQL 服务器;确保相应地设置防火墙规则。

注意 2:如果您使用bind-address = 172.17.42.1MySQL 服务器,则不会侦听与127.0.0.1. 在 docker 主机上运行的想要连接到 MySQL 的进程必须使用172.17.42.1IP 地址。

主机模式

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

2022-02-08