我有一个Nginx在码头集装箱里运行。我在主机系统上运行了MySql。我想从我的容器中连接到MySql。MySql仅绑定到本地主机设备。

是否有任何方法可以从这个docker容器连接到这个MySql或本地主机上的任何其他程序?

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


当前回答

主机上的服务器正在监听端口5000;它将从主机发回一个字符串响应作为响应

echo“主机响应”|nc-l-p 5000

docker默认在网桥模式下运行(这比在主机网络模式下运行更安全);docker中的进程获取主机上第一个网络接口的ipv4地址,该地址不是127.0.0.1;这个ipv4地址通过环境变量HOSTIP传递给docker;在docker内部有一个nc命令,该命令连接到主机ip和端口5000上的服务器;该命令还读取服务器的响应。

HOST=$(ifconfig|grep“inet”|grep-v 127.0.0.1|awk“{print$2}”| head-1|sed-n‘s/[^0-9]*\([0-9\.]*\)/\1/p');docker run-e HOSTIP=“${HOST}”--rm-it alpine/bin/sh-c'echo“来自容器的问候语”|nc$HOSTIP 5000-v'

计算第一个列出接口的ipv4地址的表达式在osx和linux上确实有效:

HOST=$(ifconfig|grep“inet”|grep-v 127.0.0.1|awk“{print$2}”| head-1|sed-n‘s/[^0-9]*\([0-9\.]*\)/\1/p')

让它更通用:您可以在另一个docker容器中运行服务器,如下所示:

docker run--expose 5000-p:5000:5000--rm-it alpine/bin/sh-c'echo“来自主机的响应”|nc-l-p 5000'

--暴露5000码头集装箱可以接受端口5000上的连接

-p:5000:5000主机端的docker引擎监听任何接口上的端口5000,并将连接转发到容器网络(nc正在运行)的端口5000。

其他回答

我不同意托马斯列维尔的回答。

将mysql绑定到172.17.42.1将阻止其他程序使用主机上的数据库来访问它。只有在所有数据库用户都已固定的情况下,这才有效。

将mysql绑定到0.0.0.0将向外部世界打开数据库,这不仅是一件非常糟糕的事情,而且与最初的问题作者想要做的相反

回答ivant的评论

“为什么不将mysql也绑定到docker0?”

这是不可能的。mysql/mariadb文档明确表示不可能绑定到多个接口。只能绑定到0、1或所有接口。

因此,我还没有找到从docker容器访问主机上(仅限于本地主机)数据库的任何方法。这显然是一种非常常见的模式,但我不知道怎么做。

尽管有很多冗长而令人困惑的答案,但还是有一个简短的答案。如果您的docker网桥网络为172.17.0.0/16,请执行以下操作:

将容器绑定到172.17.0.1,例如-p 172.17.0.1:8080:8080(Docker网桥网络中的网关)只需访问172.17.0.1端口8080,例如curlhttp://172.17.0.1:8080/来自其他容器

如果你使用docker compose,也许它可以工作:

iptables -I INPUT ! -i eth0 -p tcp --dport 8001 -j ACCEPT

eth0是连接internet的网络接口,8081是主机服务器端口

iptables规则的最佳方式是iptables TRACE

Linux解决方案(内核>=3.6)。

好的,本地主机服务器有一个默认的docker接口docker0,IP地址为172.17.0.1。容器以默认网络设置--net=“bridge”启动。

为docker0接口启用route_localnet:$sysctl-w net.ipv4.conf.docker0.route_localnet=1将这些规则添加到iptables:$iptables-t nat-I预路由-I docker0-d 172.17.0.1-p tcp--dport 3306-j DNAT--to 127.0.0.1:3306$iptables-t filter-I INPUT-I docker0-d 127.0.0.1-p tcp--dport 3306-j ACCEPT创建具有从“%”访问权限的MySQL用户,这意味着-来自任何人,不包括本地主机:CREATE USER“USER”@“%”IDENTIFIED BY“password”;在脚本中将mysql服务器地址更改为172.17.0.1。

从内核文档中:

route_localnet-BOOLEAN:在路由时,不要将环回地址视为火星源或目的地。这允许将127/8用于本地路由目的(默认为FALSE)。

在修复程序未合并到主分支之前,只需从容器内部运行主机IP即可:

ip -4 route list match 0/0 | cut -d' ' -f3

(正如@Mahoney在这里所建议的)。