我有一个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的主机的端口。

其他回答

试试看:

version: '3.5'
services:
  yourservice-here:
    container_name: container_name
    ports:
      - "4000:4000"
    extra_hosts: # <---- here
      - localhost:192.168.1.202
      - or-vitualhost.local:192.168.1.202

要获取192.168.1.202,请使用ifconfig

这对我有用。希望能帮上忙!

这在NGINX/PHP-FPM堆栈上对我有效,而无需接触任何代码或网络,应用程序只是希望能够连接到本地主机

将mysqld.sock从主机装载到容器内部。

在运行mysql的主机上查找mysql.sock文件的位置:netstat-ln|awk'/mysql(.*)?\。袜子/{打印$9}'

将该文件装载到docker中预期的位置:docker运行-v/hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock

mysqld.sock的可能位置:

/tmp/mysqld.sock
/var/run/mysqld/mysqld.sock 
/var/lib/mysql/mysql.sock
/Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP

编辑:我最终在GitHub上制作了这个概念的原型。退房:https://github.com/sivabudh/system-in-a-box


首先,我的答案面向两组人:使用Mac的人和使用Linux的人。

主机网络模式在Mac上不起作用。您必须使用IP别名,请参阅:https://stackoverflow.com/a/43541681/2713729

什么是主机网络模式?参见:https://docs.docker.com/engine/reference/run/#/network-设置

其次,对于那些正在使用Linux的人(我的直接经验是Ubuntu 14.04 LTS,我很快就会升级到16.04 LTS),是的,您可以让Docker容器中运行的服务连接到Docker主机上运行的localhost服务(例如,您的笔记本电脑)。

How?

关键是当你运行Docker容器时,你必须以主机模式运行它。命令如下所示:

docker run--network=“host”-id<docker image id>

当你在容器中执行ifconfig(你需要apt-get-install-net-tools你的容器才能调用ifconfig)时,你会看到网络接口与Docker主机上的相同(例如你的笔记本电脑)。

需要注意的是,我是Mac用户,但我在Parallels下运行Ubuntu,所以使用Mac不是缺点

这就是将NGINX容器连接到本地主机上运行的MySQL的方法。

您可以使用alpine映像获取主机ip

docker run --rm alpine ip route | awk 'NR==1 {print $3}'

这将更加一致,因为您总是使用alpine来运行命令。

类似于Mariano的回答,您可以使用相同的命令设置环境变量

DOCKER_HOST=$(docker run --rm alpine ip route | awk 'NR==1 {print $3}') docker-compose up

CGroups和Namespaces在容器生态系统中发挥着重要作用。

命名空间提供了一层隔离。每个容器都在一个单独的命名空间中运行,其访问权限仅限于该命名空间。Cgroups控制每个容器的资源利用率,而Namespace控制进程可以看到和访问相应资源的内容。

以下是您可以遵循的解决方案方法的基本理解,

使用网络命名空间

当容器从图像中产生时,将定义并创建网络接口。这为容器提供了唯一的IP地址和接口。

$ docker run -it alpine ifconfig

通过将名称空间更改为主机,陪护者网络不会与其接口保持隔离,进程将可以访问主机网络接口。

$ docker run -it --net=host alpine ifconfig

如果进程在端口上侦听,它们将在主机接口上侦听并映射到容器。

使用PID命名空间通过更改Pid名称空间,容器可以与超出其正常范围的其他进程进行交互。

此容器将在其自己的命名空间中运行。

$ docker run -it alpine ps aux

通过将命名空间更改为主机,容器还可以看到系统上运行的所有其他进程。

$ docker run -it --pid=host alpine ps aux

共享命名空间

在生产中这样做是一种糟糕的做法,因为您正在打破容器安全模型,这可能会导致漏洞,并容易被窃听。这只是为了调试工具和了解容器安全中的漏洞。

第一个容器是nginx服务器。这将创建一个新的网络和进程命名空间。该容器将自身绑定到新创建的网络接口的端口80。

$ docker run -d --name http nginx:alpine

另一个容器现在可以重用这个名称空间,

$ docker run --net=container:http mohan08p/curl curl -s localhost

此外,此容器可以看到与共享容器中的进程的接口。

$ docker run --pid=container:http alpine ps aux

这将允许您在不更改或重新启动应用程序的情况下授予容器更多权限。以类似的方式,您可以连接到主机上的mysql,运行并调试应用程序。但是,不建议这样做。希望有帮助。