Docker 命令中的—— net = host 选项真正起什么作用?

我对 Docker 还是个新手。在 docker run 命令中,我找不到任何关于这个选项的清晰描述,对此深感困惑。

我们是否可以使用它来访问运行在多克容器上的应用程序而不指定端口?作为一个例子,如果我在8080端口通过 Docker run 命令中的 -p 8080:8080选项运行一个通过 Docker 映像部署的 webapp,我知道我必须在 Docker 容器 ip/theWebAppName 上的8080端口访问它。但我实在想不出 --net=host选项是如何工作的。

193253 次浏览

在 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

在 jenkins 的 dockerfile 中,端口 808050000是公开的。那些港口是为集装箱在其桥梁网络上开放的。因此,桥网络中的一切都可以访问端口 808050000上的容器。桥接网络中的一切都在 "Subnet": "172.17.0.0/16",的私有范围内,如果你想从外部访问它们,你必须用 -p 8080:8080映射端口。这将把容器的端口映射到实际服务器(主机网络)的端口。因此访问 8080上的服务器将路由到端口 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上的服务器时,我正在访问我的 Jenkins。我认为 这个博客对于更好地理解它也是有用的。

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

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

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

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

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

一般来说,--net=host只有在您运行具有非常特殊的、不寻常的网络需求的程序时才需要。

最后,从安全的角度来看,Docker 容器可以监听许多端口,即使它们只公布(公开)一个端口。正常情况下,这样做是可以的,因为您只转发预期的单个端口,但是如果使用 --net=host,那么您将获得 所有,即使那些没有在 Dockerfile 中列出的容器端口,也会监听主机。这意味着您需要仔细检查容器(特别是如果它不是您的,例如由软件项目提供的正式容器) ,以确保您不会无意中暴露机器上的额外服务。

请记住一点,主机网络驱动程序只能在 Linux 主机上工作,不支持在 Mac 上使用 Docker Desktop,Windows 上使用 Docker Desktop,Windows 服务器上使用 Docker EE