我有个码头集装箱在运行詹金斯。作为构建过程的一部分,我需要访问在主机上本地运行的web服务器。是否有一种方法可以将主机web服务器(可以配置为在端口上运行)暴露给jenkins容器?

我在Linux机器上本机运行docker。

更新:

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

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

当前回答

当你“已经”创建了两个docker映像,并且你想让两个容器彼此通信时。

为此,您可以方便地使用自己的——name运行每个容器,并使用——link标志来启用它们之间的通信。但是在docker构建期间你不会得到这个。

当你和我一样身处险境时,那是你的

docker build -t "centos7/someApp" someApp/ 

当你尝试的时候,它就会被打破

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

你会被“curl/wget”卡住,返回没有“到主机的路由”。

原因是docker设置的安全性,默认情况下禁止容器与主机或主机上运行的其他容器通信。 这让我很惊讶,我必须说,你会期望在本地机器上运行的docker机器的回声系统能够完美地相互访问,没有太多障碍。

对此的解释将在以下文档中详细描述。

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

本文给出了两个快速解决方案,可以帮助您降低网络安全性。

最简单的选择是关闭防火墙——或者允许所有防火墙。这意味着运行必要的命令,可以是systemctl stop firewall, iptables -F或等效命令。

其他回答

在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接口。


如果你在MacOS或Windows 18.03+上使用Docker,你可以连接到神奇的主机名host.docker.internal。


最后,在Linux下你可以通过设置——net=host在主机网络命名空间中运行容器;在这种情况下,主机上的localhost与容器内的localhost相同,因此容器化服务将像非容器化服务一样,无需任何额外配置即可访问。

当你“已经”创建了两个docker映像,并且你想让两个容器彼此通信时。

为此,您可以方便地使用自己的——name运行每个容器,并使用——link标志来启用它们之间的通信。但是在docker构建期间你不会得到这个。

当你和我一样身处险境时,那是你的

docker build -t "centos7/someApp" someApp/ 

当你尝试的时候,它就会被打破

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

你会被“curl/wget”卡住,返回没有“到主机的路由”。

原因是docker设置的安全性,默认情况下禁止容器与主机或主机上运行的其他容器通信。 这让我很惊讶,我必须说,你会期望在本地机器上运行的docker机器的回声系统能够完美地相互访问,没有太多障碍。

对此的解释将在以下文档中详细描述。

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

本文给出了两个快速解决方案,可以帮助您降低网络安全性。

最简单的选择是关闭防火墙——或者允许所有防火墙。这意味着运行必要的命令,可以是systemctl stop firewall, iptables -F或等效命令。

对于使用桥接网络在容器之间创建专用网络的docker-compose,使用docker0的公认解决方案不起作用,因为容器的出口接口不是docker0,而是一个随机生成的接口id,例如:

$ ifconfig

br-02d7f5ba5a51: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.32.1  netmask 255.255.240.0  broadcast 192.168.47.255

不幸的是,随机id是不可预测的,并且每次compose必须重新创建网络时(例如在主机重新启动时)都会改变。我的解决方案是在一个已知的子网中创建私有网络,并配置iptables以接受该范围:

撰写文件片段:

version: "3.7"

services:
  mongodb:
    image: mongo:4.2.2
    networks:
    - mynet
    # rest of service config and other services removed for clarity

networks:
  mynet:
    name: mynet
    ipam:
      driver: default
      config:
      - subnet: "192.168.32.0/20"

如果您的环境需要,您可以更改子网。我使用docker network inspect任意选择了192.168.32.0/20,以查看默认创建的内容。

在主机上配置iptables,允许私有子网作为源:

$ iptables -I INPUT 1 -s 192.168.32.0/20 -j ACCEPT

这是最简单的iptables规则。您可能希望添加其他限制,例如按目的端口。当你对iptables的工作感到满意时,不要忘记坚持你的规则。

这种方法的优点是可重复的,因此是可自动化的。我使用ansible的模板模块使用变量替换来部署我的compose文件,然后使用iptables和shell模块分别配置和持久化防火墙规则。

适用于所有平台

Docker v 20.10及以上版本(自2020年12月14日起)

在Linux上,在Docker命令中添加——add-host=host.docker.internal:host-gateway来启用该功能。(Docker Compose配置见下文)

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

要在Linux上的Docker Compose中启用此功能,请在容器定义中添加以下行: extra_hosts: ——“host.docker.internal: host-gateway”

适用于macOS和Windows

Docker v 18.03及以上版本(自2018年3月21日起)

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

Linux支持未决https://github.com/docker/for-linux/issues/264

MacOS和早期版本的Docker

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代替。

Docker适用于Mac 17.05及以下版本

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

sudo ifconfig lo0又名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

在docker run命令中使用——net="host",那么docker容器中的localhost将指向docker主机。