Docker命令中的--net = host选项实际上是做什么的?


90

我是Docker的初学者。我在docker run命令中找不到对此选项的任何清晰描述,对此有些困惑。

我们可以在不指定端口的情况下使用它来访问在docker容器上运行的应用程序吗?作为示例,如果我使用-p 8080:8080docker run命令中的选项运行通过端口8080中的docker映像部署的webapp ,我知道我将必须在Docker容器ip / theWebAppName的8080端口上访问它。但是我真的无法想到--net=host期权的运作方式。

Answers:


127

在docker安装之后,默认情况下您具有3个网络:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

我试图保持这种简单。因此,如果默认情况下启动容器,它将在网桥(docker0)网络内部创建。

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

在詹金斯的dockerfile中,端口808050000被暴露。这些端口在其桥接网络上为容器打开。因此,该桥接网络中的所有内容都可以访问端口8080和上的容器50000。桥接网络中的所有内容都在的私有范围内。"Subnet": "172.17.0.0/16",如果要从外部访问它们,则必须使用映射端口-p 8080:8080。这会将容器的端口映射到真实服务器(主机网络)的端口。因此,在上访问服务器8080将路由到port上的网桥8080

现在您也有了主机网络。不会将容器网络化。因此,如果您在主机网络中启动一个容器,它将看起来像这样(这是第一个容器):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

不同之处在于端口。您的容器现在位于主机网络中。因此,如果您8080在主机上打开端口,则将立即访问该容器。

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

我已经8080在防火墙中打开了端口,当我现在在端口上8080访问服务器时,我正在访问我的詹金斯。我认为此博客对于更好地了解它也很有用。


4
是否可以--net=host在Dockerfile中添加该选项?
AnirbanDebnath

6
@AnirbanDebnath我认为不可能将其放在dockerfile中,但是由于docker v17,您可以将其用作docker build:的参数docker build --network=host。用于docker构建的指定主机网络仅用于下载构建映像所需的软件包。当您想在主机网络上运行容器时,仍然需要定义--network = host选项。
lvthillo

是@AnirbanDebnath,在Dockerfile中允许使用。例如在v3中- network_mode: "host"ref-docs.docker.com/compose/compose-file/#network_mode
Mohnish

这是一个Docker-Compose文件,描述了如何运行容器。不是Dockerfile。但是确实,有可能并且与docker run --network = host
lvthillo

27

--net=host从网络的角度来看,选项用于使Docker容器中的程序看起来像在主机本身上运行。它允许容器提供比正常情况下更大的网络访问权限。

通常,您必须将端口从主机转发到容器中,但是当容器共享主机的网络时,任何网络活动都直接在主机上发生-就像程序在主机本地运行而不是在主机内部运行一样容器。

虽然这的确意味着您不再需要公开端口并将其映射到容器端口,但这意味着您必须编辑Dockerfile来调整每个容器侦听的端口,以避免冲突,因为您不能让两个容器在同一容器上运行主机端口。但是,此选项的真正原因是正在运行需要网络访问的应用程序,这些应用程序很难在端口级别转发到容器。

例如,如果要运行DHCP服务器,则需要能够侦听网络上的广播流量,并从数据包中提取MAC地址。此信息在端口转发过程中丢失,因此在Docker中运行DHCP服务器的唯一方法是将容器运行为--net=host

一般来说, --net=host仅当您运行的程序具有非常特殊的,异常的网络需求时才需要。

最后,从安全角度来看,即使Docker容器仅通告(公开)单个端口,也可以侦听许多端口。通常情况下,这是好的,你只转发单一端口的预期,但是如果你使用--net=host,你会得到所有容器的端口上侦听主机上,即使是那些没有在Dockerfile上市。这意味着您将需要仔细检查容器(尤其是如果不是您自己的容器,例如软件项目提供的官方容器),以确保您不会无意间在机器上暴露了额外的服务。


如果使用“ --net = host”选项启动多个容器,将发生什么情况?是否将请求转发到随机容器?
user482594

@ user482594:它们都将共享同一网络堆栈,就像您在同一容器中运行所有程序一样。例如,如果您运行两个Web服务器,则需要确保它们正在侦听不同的端口,否则第二个容器将收到一个错误,表明第一个容器正在使用该端口。在此设置中,传入的流量将转发到正在侦听的任何容器(技术上所有--net=host容器都将看到该流量,但是当然,无论您在哪个容器中运行,一次只能有一个程序可以侦听给定端口)。
恶意

1
  1. 您可以创建自己的新网络,例如 --net =“ anyname”
  2. 这样做是为了隔离不同容器中的服务。
  3. 假设同一服务在不同的容器中运行,但是端口映射保持不变,第一个容器启动良好,但是第二个容器中的相同服务将失败。为了避免这种情况,请更改端口映射或创建网络。

1
感谢您提及“ 2.这样做是为了将(网络)服务与其他容器隔离开”。host如果有可能在同一主机上运行多个容器,我真的看到使用其他docker网络配置(除外)的价值。在其他情况下(不需要网络隔离),我更愿意--net=host
CᴴᴀZ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.