Docker命令中的--net = host选项真的有用吗?

Rav*_*ndo 56 docker docker-networking

我是Docker的初学者.我找不到任何关于此选项在docker run命令中做什么的明确描述,并且对它有点困惑.

我们可以使用它来访问在docker容器上运行的应用程序而无需指定端口吗?举个例子,如果我使用-p 8080:8080docker run命令中的选项运行通过端口8080中的docker镜像部署的webapp ,我知道我将不得不在Docker容器ip/theWebAppName上的8080端口上访问它.但我真的想不出--net=host选项如何运作的方式.

lvt*_*llo 97

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

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local
Run Code Online (Sandbox Code Playgroud)

我想保持这个简单.因此,如果您默认启动容器,它将在桥(docker0)网络内创建.

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell
Run Code Online (Sandbox Code Playgroud)

在jenkins的dockerfile中,端口808050000暴露.这些端口在其桥接网络上为容器打开.这样桥接网络里面一切都可以在端口访问容器808050000.桥接网络中的所有内容都在私有范围内."Subnet": "172.17.0.0/16",如果要从外部访问它们,则必须映射端口-p 8080:8080.这会将容器的端口映射到真实服务器的端口(主机网络).因此,访问您的服务器8080将路由到端口上的bridgenetwork 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
Run Code Online (Sandbox Code Playgroud)

区别在于端口.您的容器现在位于主机网络中.因此,如果您8080在主机上打开端口,您将立即访问容器.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

8080在防火墙上打开了端口,当我现在8080正在访问我的服务器端口时,我正在访问我的jenkins.我认为这个博客对于更好地理解它也很有用.

  • @AnirbanDebnath我不认为将它放在dockerfile中是可能的,但是自docker v17以来你可以将它用作docker build的参数:`docker build --network = host`.docker build的指定主机网络仅用于下载构建映像所需的包.如果要在主机网络上运行容器,则仍需要定义--network = host选项. (5认同)
  • 是否可以在Dockerfile中添加选项--net = host? (2认同)
  • 是的@AnirbanDebnath,它在 Dockerfile 中是允许的。例如,在 v3 中 -- `network_mode: "host"` (参考 - https://docs.docker.com/compose/compose-file/#network_mode) (2认同)
  • 这是一个 Docker-Compose 文件,描述了如何运行容器。不是 Dockerfile。但事实上,这是可能的,并且与 docker run --network=host 做同样的事情 (2认同)

小智 23

请记住一点,主机网络驱动程序仅适用于 Linux 主机,并且在 Docker Desktop for Mac、Docker Desktop for Windows 或 Docker EE for Windows Server 上不受支持

  • 另请注意,适用于 Windows/Mac 的 Docker 不会警告您它不起作用 - 它只是静默运行容器并且不会绑定到任何本地端口。 (13认同)

Mal*_*ous 9

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

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

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

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

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

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


Abh*_*D K 7

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

  • 感谢您提到“2.这样做是为了将(网络)服务与不同容器隔离”。如果有可能在同一主机上运行多个容器,我确实看到了使用其他 docker 网络配置(“主机”除外)的价值。在其他情况下(不需要网络隔离),我更喜欢“--net=host”。 (2认同)