Docker容器如何访问互联网

7

我已经安装了Docker(Mac版)。 使用以下命令启动新的容器:

docker run -it ubuntu

我可以通过简单调用命令来确认我的新创建的容器已经连接到了互联网。

ping google.com

我明白:

root@b06e1a46cc40:/# ping google.com
PING google.com (216.58.209.14) 56(84) bytes of data.
64 bytes from sof01s12-in-f14.1e100.net (216.58.209.14): icmp_seq=1 ttl=37 time=63.0 ms
64 bytes from sof01s12-in-f14.1e100.net (216.58.209.14): icmp_seq=2 ttl=37 time=63.7 ms
64 bytes from sof01s12-in-f14.1e100.net (216.58.209.14): icmp_seq=3 ttl=37 time=64.8 ms

接下来,我检查了我的容器连接的网络:

root@b06e1a46cc40:/# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1
    link/tunnel6 :: brd ::
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@b06e1a46cc40:/#

据我所知,eth0用于访问互联网 - 它是一个172.17.0.0/16网络。

当我查看主机的网络列表时,我没有连接到这个网络。

那么我的容器如何访问互联网呢?

据我理解,我的容器应该通过我的主机访问互联网,因为毕竟我的主机已经连接到了互联网,这是唯一的访问方式。


我在考虑这样的答案:在 Mac 上,我的容器实际上是在后台运行的 VM 上运行的。因此,有如下层次结构:我的主机(Mac)-> VM(Linux)-> 容器(Ubuntu)。所以,容器的网络(桥接)可能连接容器和 VM。然后,VM 连接到一些网络,该网络也被我的主机使用(那将是哪个网络?如何检查?)。这就是容器访问互联网的方式。我是对的吗? - mnj
3个回答

6

Docker for Mac使用macOS Hypervisor framework来运行一个虚拟机中的自定义Linux发行版(CLD)。

现在,虚拟机内部的CLD与主机操作系统(即macOS)没有网络连接,但是Docker for Mac通过VPNkit填补了这个空缺。

VPNkit使用共享内存队列在主机和客户机之间发送网络数据包,然后将它们注入到另一侧的网络堆栈中。

以下是一些相关文章,详细介绍了这些内容的工作原理:

https://docs.docker.com/docker-for-mac/networking/ https://github.com/moby/vpnkit/blob/master/docs/ethernet.md https://github.com/moby/vpnkit/blob/master/docs/ports.md

因此,直接回答你的问题——你在容器内看到的网络/接口在主机(macOS)上没有对应物。相反,当你运行ping google.com时,VPNkit在VM中拦截结果的网络数据包,将其传输到主机并注入主机的网络堆栈。
入站数据包也是如此,但方向相反。

相同的情况也会发生在入站数据包上,但是方向相反。这是否意味着无论哪个接口的所有传入流量都将通过vpnkit进行处理? - zevarito

1

是的,我理解这一点。但是,桥接网络如何允许访问互联网呢? - mnj

0

在启动时使用主机网络 docker run -it --network host ubuntu


@Imlmvxi 这并没有真正回答我的问题。我想了解默认(桥接)网络如何让我连接到互联网 - 这怎么可能呢?我知道桥接是一个默认情况下所有容器都连接到的网络 - 所以它们可以相互通信。 - mnj
默认网络是主机的iptables nat实现。 - lmlmvxi
@lmlmvxi,您的意思是docker默认使用iptables为容器创建隔离路由网络。但是对于macOS和Docker桌面版来说,这并不是真的。 - Paul-Sebastian Manole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接