我有一个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地址的可达性。


当前回答

非常简单快速,使用ifconfig(linux)或ipconfig(windows)检查主机IP,然后创建docker-compose.yml:

version: '3' # specify docker-compose version
services:
  nginx:
    build: ./ # specify the directory of the Dockerfile
    ports:
      - "8080:80" # specify port mapping
    extra_hosts:
      - "dockerhost:<yourIP>"

这样,您的容器将能够访问主机。访问DB时,请记住使用之前指定的名称,在本例中是dockerhost和运行DB的主机的端口。

其他回答

我做了一个类似于上述帖子的黑客,获取本地IP以映射到容器中的别名(DNS)。主要问题是使用一个在Linux和OSX中都有效的简单脚本动态获取主机IP地址。我在两种环境中都使用了这个脚本(即使在配置了“$LANG”!=“en_*”的Linux发行版中也是如此):

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

因此,使用Docker Compose,完整的配置将是:

启动脚本(docker run.sh):

export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)
docker-compose -f docker-compose.yml up

docker-compose.yml文件:

myapp:
  build: .
  ports:
    - "80:80"
  extra_hosts:
    - "dockerhost:$DOCKERHOST"

然后改变http://localhost到http://dockerhost在您的代码中。

有关如何定制DOCKERHOST脚本的更高级指南,请阅读本文并解释其工作原理。

我通过在MySQL中为容器的ip创建一个用户来解决这个问题:

$ sudo mysql<br>
mysql> create user 'username'@'172.17.0.2' identified by 'password';<br>
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on database_name.* to 'username'@'172.17.0.2' with grant option;<br>
Query OK, 0 rows affected (0.00 sec)

$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
<br>bind-address        = 172.17.0.1

$ sudo systemctl restart mysql.service

然后在容器上:jdbc:mysql://<b>172.17.0.1</b>:3306/database_name

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

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

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

回答ivant的评论

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

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

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

您可以为计算机使用网络别名

OSX

sudo ifconfig lo0 alias 123.123.123.123/24 up

LINUX操作系统

sudo ifconfig lo:0  123.123.123.123 up

然后从容器中,您可以通过123.123.123.123看到机器

另外一点可能很有用,特别是对于docker容器中的NGINX服务器配置。因此,如果您的主机服务应该出于不同的目的读取客户端的url,则可以对其进行定义,只需稍微修改前面在答案中提到的方法即可:

--add-host brand-A-client.local:host-gateway

或在docker-compose.yml中

extra_hosts:
- brand-B-client.local:host-gateway

并在容器中分别引用它们。适用于Docker Windows/Macos/Linux。