首页 文章

如何从docker容器访问主机端口

提问于
浏览
123

我有一个运行jenkins的docker容器 . 作为构建过程的一部分,我需要访问在主机上本地运行的Web服务器 . 有没有办法将主机Web服务器(可以配置为在端口上运行)暴露给jenkins容器?

编辑:我正在Linux机器上本地运行docker .

更新:

除了下面的@larsks答案,要从主机获取主机IP的IP地址,我执行以下操作:

ip addr show docker0 | grep -Po 'inet \K[\d.]+'

8 回答

  • 4

    对于macOS和Windows

    Docker v 18.03 and above (since March 21st 2018)

    使用内部IP地址或连接到特殊DNS名称 host.docker.internal ,它将解析为主机使用的内部IP地址 .

    Linux支持等待https://github.com/docker/for-linux/issues/264

    MacOS与早期版本的Docker

    Docker for Mac v 17.12 to v 18.02

    与上面相同但使用 docker.for.mac.host.internal 代替 .

    Docker for Mac v 17.06 to v 17.11

    与上面相同但使用 docker.for.mac.localhost 代替 .

    Docker for Mac 17.05 and below

    要从docker容器访问主机,必须将IP别名附加到网络接口 . 你可以绑定你想要的任何IP,只要确保你没有将它用于其他任何东西 .

    sudo ifconfig lo0 alias 123.123.123.123/24

    然后确保您的服务器正在侦听上述IP或 0.0.0.0 . 如果它正在侦听localhost 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

  • 17

    目前在Mac和Windows上最简单的方法是使用主机host.docker.internal,它解析为主机的IP地址 . 不幸的是does not work on linux yet(截至2018年4月) .

  • 0

    docker run 命令中使用 --net="host" ,然后docker容器中的 localhost 将指向您的泊坞主机 .

  • 5

    如果您已经“创建”了两个泊坞窗图像,并且您希望将两个容器放在一起进行通信 .

    为此,您可以方便地使用自己的--name运行每个容器,并使用--link标志来启用它们之间的通信 . 但是在docker build期间你没有得到这个 .

    当你在像我这样的场景中,这是你的

    docker build -t "centos7/someApp" someApp/
    

    当你尝试时,这会打破

    curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz
    

    并且你被困在“curl / wget”没有返回“路由到主机” .

    原因是docker设置了安全性,默认情况下禁止从容器到主机或主机上运行的其他容器的通信 . 这对我来说是非常令人惊讶的,我必须说,你会期望在本地机器上运行的docker机器的echosystem只是完美无缺地可以互相访问而没有太多障碍 .

    以下文档中详细描述了对此的解释 .

    http://www.dedoimedo.com/computers/docker-networking.html

    通过降低网络安全性,可以提供两种快速解决方法,帮助您实现目标 .

    最简单的替代方案就是关闭防火墙 - 或者允许所有防火墙 . 这意味着运行必要的命令,可以是systemctl stop firewalld,iptables -F或等效命令 .

    希望这些信息可以帮助您 .

  • 150

    我已经探索了各种解决方案,我觉得这是最不讨厌的解决方案:

    • 定义网桥IP的静态IP地址 .

    • 将网关IP添加为hosts文件中的额外条目 .

    唯一的缺点是如果你有多个网络或项目这样做,你必须确保他们的IP地址范围不冲突 .

    这是一个Docker Compose示例:

    version: '2.3'
    
    services:
      redis:
        image: "redis"
        extra_hosts:
          - "dockerhost:172.20.0.1"
    
    networks:
      default:
        ipam:
          driver: default
          config:
          - subnet: 172.20.0.0/16
            gateway: 172.20.0.1
    

    然后,您可以使用主机名“dockerhost”从容器内部访问主机上的端口 .

  • 1

    使用docker-compose的解决方案:要访问基于主机的服务,您可以使用 network_mode 参数https://docs.docker.com/compose/compose-file/#network_mode

    version: '3'
    services:
      jenkins:
        network_mode: host
    
  • 114

    我创建了一个docker容器来完成https://github.com/qoomon/docker-host

    然后,您可以简单地使用容器名称dns来访问主机系统,例如 curl http://dockerhost:9200

  • 2

    在Linux上本机运行Docker时,您可以使用 docker0 接口的IP地址访问主机服务 . 从容器内部,这将是您的默认路由 .

    例如,在我的系统上:

    $ ip addr show docker0
    7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
        link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::f4d2:49ff:fedd:28a0/64 scope link 
           valid_lft forever preferred_lft forever
    

    在容器内:

    # ip route show
    default via 172.17.0.1 dev eth0 
    172.17.0.0/16 dev eth0  src 172.17.0.4
    

    使用简单的shell脚本提取此IP地址相当容易:

    #!/bin/sh
    
    hostip=$(ip route show | awk '/default/ {print $3}')
    echo $hostip
    

    您可能需要修改主机上的 iptables 规则以允许来自Docker容器的连接 . 像这样的东西可以解决这个问题:

    # iptables -A INPUT -i docker0 -j ACCEPT
    

    这将允许从Docker容器访问主机上的任何端口 . 注意:

    • iptables规则是有序的,这个规则可能会也可能不会做正确的事情,这取决于它之前的其他规则 .

    • 您将只能访问(a)监听 INADDR_ANY (又名0.0.0.0)或明确监听 docker0 接口的主机服务 .

相关问题