代码之家  ›  专栏  ›  技术社区  ›  Maisen1886

docker组成网络访问主机外端口

  •  0
  • Maisen1886  · 技术社区  · 3 年前

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

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

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

    0 回复  |  直到 2 年前
        1
  •  4
  •   ymochurad    1 年前

    编辑

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

    如果您正在使用 Linux Docker 20.10.0+,您也可以使用主机 host.docker.internal 如果 您使用启动Docker容器 --add-host host.docker.internal:host-gateway 选项,或者在docker-compose.yml文件中添加以下代码段:

    extra_hosts:
        - "host.docker.internal:host-gateway"
    

    否则,请阅读以下内容


    太长,读不下去了

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

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


    docker容器网络模式注意事项

    Docker优惠 different networking modes 运行容器时。根据您选择的模式,您将以不同的方式连接到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主机有IP地址 172.17.42.1 码头工人0 网络接口。

    现在启动一个新容器,并在上面获得一个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
    

    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.17.42.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服务器将侦听所有网络接口上的连接。这意味着你的MySQL服务器可以从互联网上访问;确保相应地设置防火墙规则。

    注2: 如果您使用 绑定地址=172.17.42.1 您的MySQL服务器不会侦听到的连接 127.0.0.1 。在docker主机上运行的要连接到MySQL的进程必须使用 172.17.42.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套接字进行连接。