社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

如何在docker container proxy_pass中配置nginx来自行托管它?[复制品]

pvd • 5 年前 • 2004 次点击  

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

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

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/43192
 
2004 次点击  
文章 [ 19 ]  |  最新文章 5 年前
Stephens
Reply   •   1 楼
Stephens    7 年前

你可以使用 ngrok 创建到本地主机的安全隧道,然后将该隧道公开到Docker容器。

NgRok自2017年5月22日起免费使用。

步骤:

1)去 恩格罗克

2) download ngrok客户端并遵循安装说明

3) SIGN UP 对于帐户,它们将提供身份验证令牌。需要注册,因为ngrok只在注册后提供tcp端口隧道。报名不需要任何费用或信用卡。

4)在您的终端 ngrok tcp 3306 . 3306 是mysql在本地运行的端口,您也可以使用任何其他端口。

5)您将从步骤接收地址 4 例如: tcp://0.tcp.ngrok.io:10117 . 这是到本地计算机的隧道连接。 0.tcp.ngrok.io 被映射到 localhost 港口 10117 映射到本地端口 三千三百零六 . 现在您可以使用这个地址从任何地方访问本地主机端口3306,包括在这台机器上运行的任何Docker容器。在Docker容器(无论它在哪里)中,假设已经安装了MySQL客户端,请执行以下操作:

mysql --host 0.tcp.ngrok.io --port 10117 -u root

您将能够登录到 root 从Docker容器中获取本地计算机的帐户!

我在博客上讨论过这个解决方案,请查看更多详细信息 here

patryk.beza
Reply   •   2 楼
patryk.beza    6 年前

直到 fix 未合并到 master 分支,要获取主机IP,只需从容器内部运行:

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

(根据建议 @Mahoney here )

Felipe Toledo
Reply   •   3 楼
Felipe Toledo    6 年前

非常简单快速,用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>"

这样,您的容器将能够访问您的主机。访问数据库时,请记住使用之前指定的名称,在本例中为“dockerhost”,以及运行数据库的主机端口

Elad
Reply   •   4 楼
Elad    6 年前

在Windows 10 Home上使用Docker工具箱时,没有一个答案对我有效,但是 100.2.2 是的,因为它使用了virtualbox,它向这个地址上的vm公开主机。

Lokesh S
Reply   •   5 楼
Lokesh S    6 年前

对于Windows计算机:

运行下面的命令在构建期间随机公开docker端口

$docker run -d --name MyWebServer -P mediawiki

enter image description here

enter image description here

在上面的容器列表中,您可以看到指定为32768的端口。尝试访问

localhost:32768 

您可以看到mediawiki页面

mohan08p
Reply   •   6 楼
mohan08p    7 年前

cgroup和命名空间在容器生态系统中扮演着重要角色。

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

以下是您对解决方案方法的基本理解,

使用网络命名空间

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

$ docker run -it alpine ifconfig

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

$ 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,运行并调试您的应用程序。但是,不建议这样走。希望有帮助。

Bruno Bieri
Reply   •   7 楼
Bruno Bieri    8 年前

我不同意汤马斯莱维尔的回答。

将mysql绑定到172.17.42.1将阻止其他程序使用主机上的数据库访问它。只有当所有数据库用户都已停靠时,此操作才有效。

将mysql绑定到0.0.0.0将使数据库对外开放,这不仅是一件非常糟糕的事情,而且与原问题作者想要做的相反。他明确表示“mysql运行在localhost上,没有向外界公开端口,所以它绑定在localhost上”

回答伊万特的评论

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

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

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

hasnat
Reply   •   8 楼
hasnat    6 年前

您可以使用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
sopheamak
Reply   •   9 楼
sopheamak    7 年前

这是我的解决方案:对我的案子有效

  • 通过注释将本地mysql服务器设置为公共访问 #bind-address = 127.0.0.1 在/etc/mysql/mysql.conf.d中

  • 重新启动mysql服务器 sudo /etc/init.d/mysql restart

  • 运行以下命令打开用户根访问任何主机 mysql -uroot -proot GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION; FLUSH PRIVILEGES;

  • 创建sh脚本:run_docker.sh

    #!bin/bash

    HOSTIP=`ip -4 addr show scope global dev eth0 | grep inet | awk '{print \$2}' | cut -d / -f 1`


      docker run -it -d --name web-app \
                  --add-host=local:${HOSTIP} \
                  -p 8080:8080 \
                  -e DATABASE_HOST=${HOSTIP} \
                  -e DATABASE_PORT=3306 \
                  -e DATABASE_NAME=demo \
                  -e DATABASE_USER=root \
                  -e DATABASE_PASSWORD=root \
                  sopheamak/springboot_docker_mysql

  
  • 与Docker作曲家一起运行

    version: '2.1'
    
    

    services:
    tomcatwar: extra_hosts: - "local:10.1.2.232" image: sopheamak/springboot_docker_mysql
    ports: - 8080:8080 environment: - DATABASE_HOST=local - DATABASE_USER=root - DATABASE_PASSWORD=root - DATABASE_NAME=demo - DATABASE_PORT=3306

dansalmo
Reply   •   10 楼
dansalmo    7 年前

mac-osx的最简单解决方案

只需使用你的mac的ip地址。在Mac上运行此命令以获取IP地址并在容器内使用它:

$ ifconfig | grep 'inet 192'| awk '{ print $2}'

只要在你的mac上本地运行或者在另一个docker容器中运行的服务器正在监听0.0.0.0,docker容器就可以在那个地址进行访问。

如果您只想访问另一个监听0.0.0.0的Docker容器,可以使用172.17.0.1

qoomon
Reply   •   11 楼
qoomon    6 年前

在host.docker.internal为每个平台工作之前,您可以使用我的容器作为NAT网关,而无需任何手动设置 https://github.com/qoomon/docker-host

Community Benjamin Gruenbaum
Reply   •   12 楼
Community Benjamin Gruenbaum    7 年前

编辑:我最终在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-settings

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

怎么用?

关键是运行Docker容器时,必须使用 主办 模式。命令如下所示:

docker run --network="host" -id <Docker image ID>

当你做一个 ifconfig (你需要 apt-get install net-tools 你的集装箱 命令 在你的容器中,你会看到网络接口和Docker主机上的一样(比如你的笔记本电脑)。

需要注意的是,我是一个mac用户,但是我在parallels下运行ubuntu,所以使用mac并不是一个缺点。;-)

这就是如何将nginx容器连接到运行在 本地服务器 .

Casey
Reply   •   13 楼
Casey    8 年前

对于windows上的用户,假设您使用的是网桥网络驱动程序,则需要将mysql明确绑定到hyper-v网络接口的ip地址。

这是通过通常隐藏的c:\ programdata\mysql文件夹下的配置文件完成的。

绑定到0.0.0.0将不起作用。所需的地址也显示在docker配置中,在我的例子中是10.0.75.1。

Ralph Willgoss
Reply   •   14 楼
Ralph Willgoss    6 年前

Windows 10解决方案

Docker Community Edition 17.06.0-ce-win18 2017-06-28 (stable)

您可以使用主机的dns名称 docker.for.win.localhost ,以解析为内部IP。(警告提到的一些消息来源 windows 但应该是 win )

概述
我需要做一些类似的事情,从Docker容器连接到本地主机,它运行 Azure Storage Emulator CosmosDB Emulator .

这个 azure存储仿真程序 默认情况下侦听 127.0.0.1 ,虽然您也可以更改IP的绑定,但我正在寻找一个可以使用默认设置的解决方案。

这也适用于从Docker容器连接到 SQL Server IIS ,两者都以默认端口设置在主机上本地运行。

Ray D
Reply   •   15 楼
Ray D    7 年前

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

好的,你的本地主机服务器有默认的Docker接口 道克尔0 带IP地址 172.170.1 . 容器以默认网络设置启动 --net=“桥” .

  1. 为Docker0接口启用Route\u LocalNet:
    $ sysctl -w net.ipv4.conf.docker0.route_localnet=1
  2. 将此规则添加到iptables:
    $ iptables -t nat -I PREROUTING -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
  3. 从“%”创建具有访问权限的MySQL用户,这意味着-来自任何人,不包括本地主机:
    CREATE USER 'user'@'%' IDENTIFIED BY 'password';
  4. 将脚本中的mysql服务器地址更改为172.17.0.1


kernel documentation :

路由本地网 -布尔值:路由时不要将环回地址视为火星源或目标。这允许使用127/8进行本地路由( 默认为False )

d-_-b
Reply   •   16 楼
d-_-b    6 年前

这对我来说在nginx/php-fpm堆栈上工作,而不需要接触应用程序希望能够连接到的任何代码或网络。 localhost

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

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

将该文件装载到Docker中预期的位置:
docker run -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
Marco Altran Mariano Ruiz
Reply   •   17 楼
Marco Altran Mariano Ruiz    7 年前

我做了一个类似于上面文章的黑客攻击,让本地IP映射到容器中的别名(DNS)。主要问题是动态地使用一个简单的脚本,该脚本在 Linux和OSX主机IP地址 . 我编写的这个脚本在两种环境下都能工作(即使在linux发行版中 "$LANG" != "en_*" 配置):

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 剧本,看看 this post 并解释它是如何工作的。

Janne Annala
Reply   •   18 楼
Janne Annala    6 年前

适用于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

Thomasleveil
Reply   •   19 楼
Thomasleveil    6 年前

编辑: 如果你正在使用 Docker-for-mac Docker-for-Windows 18.03+,只需使用主机连接到mysql服务 host.docker.internal .

从Docker 18.09.3开始,这在Docker for Linux上不起作用。 fix 已于2019年3月8日提交,有望合并到代码库中。在此之前,解决方法是使用容器,如 qoomon's answer .


TLDR

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

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


关于Docker容器联网模式的说明

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

docker run--network=“桥”(默认)

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主机有IP地址 172.17.42.1 道克尔0 网络接口。

现在,启动一个新容器并在上面放置一个外壳: 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.1742.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

docker run--network=“主机”

或者,您可以使用 network settings set to host . 这样的容器将与Docker主机共享网络堆栈,从容器的角度来看, localhost (或 127.0.0.1 )将引用Docker主机。

请注意,在Docker容器中打开的任何端口都将在Docker主机上打开。而这不需要 -p or -P docker run 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

从码头的集装箱里 主办 模式:

[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.1742.1 IP地址。

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

如果需要使用网关的IP地址设置环境变量,可以在容器中运行以下代码:

export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')

然后在应用程序中,使用 DOCKER_HOST_IP 打开到MySQL的连接的环境变量。

注: 如果你使用 绑定地址=0.0.0.0 mysql服务器将监听所有网络接口上的连接。这意味着可以从Internet访问MySQL服务器;请确保相应地设置防火墙规则。

附注2: 如果你使用 绑定地址=172.17.42.1 你的mysql服务器不会监听连接到 127.0.0.1 . 在Docker主机上运行的进程要连接到MySQL,必须使用 172.1742.1 IP地址。

宿主模式

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