
Docker 容器的 IP 地址与其网络隔离有着密切的关系。每个 Docker 容器都会被分配一个独立的 IP 地址,这个 IP 地址属于 Docker 内部的虚拟网络。这种网络隔离确保每个容器都有独立的网络环境,避免容器之间的 IP 地址冲突和网络干扰。
在 Docker 容器内部,可以通过执行命令来查看容器自身的 IP 地址。通常情况下,容器的 IP 地址都是以
172.17.0.x
这样的形式出现的,这是 Docker 默认使用的 IP 地址段。需要在容器外部访问容器内部的服务,可以通过 Docker 的端口映射功能,将容器内部的端口映射到宿主机上的端口,这样就可以通过宿主机的 IP 地址和映射的端口来访问容器内部的服务。
Docker 容器的 IP 地址是通过容器网络隔离实现的,这不仅确保容器之间的网络独立性,也为容器内部的服务提供可访问性。合理地管理和使用 Docker 容器的 IP 地址和网络隔离功能,是容器化应用开发中非常重要的一部分。
四、Docker网络揭秘
Docker 之所以功能这么强大,其实就是充分利用了Linux Kernel的特性:NameSpace、CGroups、UnionFileSystem。 通过这些特性实现了资源隔离、限制与分层等。 本文这次就来揭晓Docker中的容器是如何做到网络互通的。 两台机器如果要实现通信,其实就是通过底层的网卡进行数据传输,每个网卡都有一个唯一的MAC地址,网卡又会绑定一个ip地址,只要两台机器的网络可以互通,那么这两台机器就可以进行通信。 想要实现通信,就得有两个同一网段的网卡,两个网卡必须是可以 ping 通的。 Docker在安装成功后,会在宿主机创建一个docker0网卡,这个网卡就是负责容器与宿主机之间通信的桥梁。 通过Docker创建一个容器之后,会在宿主机再创建一个网卡,也就是上面的 veth3543ea3@if7 ,容器内也会创建一个网卡。 一般成对的网卡,网卡组件名称后面的数字是连续的,比如宿主机的 @if7 和容器内的 @if8 ,正是这成对的网卡,才实现了容器与宿主机之间的通信。 这其实是利用 Linux Kernel 的特性 NameSpace 实现的网卡隔离,不同NameSpace下的网卡是独立的,就像Java程序中的package一样。 从上面的例子中看到容器与宿主机之间的通信好像并不是通过docker0网卡实现的? 其实这只是单容器的状态,可能看不出docker0的作用。 用图来表示一下单容器的网卡通信情况。 通过docker生成的 eth0和veth 两个网卡实现同一网段内的通信,而这个网卡又是桥接在docker0网卡上的。 再看下有多个容器的情况。 两个容器之间可以互相通信的原因就是因为docker0的存在,因为它们的网卡都是桥接在docker0上,所以也就有了和另一个容器通信的桥。 我们来验证一下是不是这样! 这种网络连接方法我们称为Bridge,这也是docker中默认的网络模式。 可以通过命令查看docker中的网络模式: 通过 docker network ls 命令查看到,docker提供了3种网络模式,brige模式我们已经知道了,那 host 和 none 又是什么意思呢?不妨来验证一下: 这种模式只会创建一个本地的环路网卡,无法与其他容器或宿主机进行通信。 在创建自己的network之前先来解释一下为什么要创建新的network。 我们用一个例子来演示一下不同容器之间的通信。 容器之间通过 ip 是可以正常访问的,但是有没有这种情况:如果一个容器出问题了,我们重启之后它的ip变了,那是不是其他用到这个容器的项目配置是不是都得改。 有没有可能直接通过容器名称来访问呢?来验证一下: 发现并不能 ping 通,但是可以使用别的手段来达到这个目的。 通过上面这种方式就可以做到以容器名来 ping 通其他容器,其实它就跟windows系统中在 hosts 文件里加了个映射是一样的。 可以看到创建自定义的 network 自动帮我们实现了这个功能,而且使用自定义的 network 也方便管理,不同业务类型的容器可以指定不同的 network。 不同的 network ip网段也不一样,这样也可以增加单机中可以创建的容器的数量。 在创建一个容器的时候,一般都需要讲容器需要暴露的端口映射到物理主机的相同端口或其他端口,因为在外网环境下是不方便直接连接到容器的,所以需要通过映射端口的方式,让外网访问宿主机的映射端口来访问容器。 如果想建立多个容器,势必需要端口映射,以满足不同容器使用相同端口的情况。 以上这些内容都是在单容器进行操作,容器之间通信也只是通过 docker0 实现的桥接模式。 如果要实现多机之间的docker通信,其实还是通过网卡,只不过需要其他的技术来实现了。 本章节就不在演示,到后面的章节再来分析!
Docker网络
Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理。 然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分。 因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求。 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host 首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。 Docker 中的网络接口默认都是虚拟的接口。 虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。 对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。 Docker 容器网络就利用了这项技术。 它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 veth pair)。 创建网络参数 Docker 创建一个容器的时候,会执行如下操作: 完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 可以在 docker run 的时候通过 --net 参数来指定容器的网络配置,有4个可选值: 当你安装Docker时,它会自动创建三个网络。 你可以使用以下docker network ls命令列出这些网络: Docker内置这三个网络,运行容器时,你可以使用该–network标志来指定容器应连接到哪些网络。 bridge网络代表docker0所有Docker安装中存在的网络。 除非你使用该docker run --network=选项指定,否则Docker守护程序默认将容器连接到此网络。 我们在使用docker run创建Docker容器时,可以用 --net 选项指定容器的网络模式,Docker可以有以下4种网络模式: Docker 容器默认使用 bridge 模式的网络。 其特点如下: Host 模式并没有为容器创建一个隔离的网络环境。 而之所以称之为host模式,是因为该模式下的 Docker 容器会和 host 宿主机共享同一个网络 namespace,故 Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。 换言之,Docker Container的 IP 地址即为宿主机 eth0 的 IP 地址。 其特点包括: Container 网络模式是 Docker 中一种较为特别的网络的模式。 处于这个模式下的 Docker 容器会共享其他容器的网络环境,因此,至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。 网络模式为 none,即不为 Docker 容器构造任何网络环境。 一旦Docker 容器采用了none 网络模式,那么容器内部就只能使用loopback网络设备,不会再有其他的网络资源。 Docker Container的none网络模式意味着不给该容器创建任何网络环境,容器只能使用127.0.0.1的本机网络。 自定义网络模式,docker提供了三种自定义网络驱动: bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。 建议使用自定义网桥来控制容器之间的相互通讯,还可以自动DNS解析容器名称到ip地址。 Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Overlay或Macvlan网络,你可以创建一个网络插件或远程网络进行完善的自定义和控制。 你可以根据需要创建任意数量的网络,并且可以在任何给定的时间将容器连接到这些网络中的零个或多个网络。 此外,您可以连接并断开网络中的容器,而无需重新启动容器,当容器连接到多个网络时,其外部连接通过第一个非内部网络以词法顺序提供。 接下来介绍Docker的内置网络驱动程序。 使用自定义网络启动容器 自定义网络好处: 参考:
详解 Docker 容器网络配置
Docker容器网络详解Docker在安装后自动提供3种网络,使用docker network ls命令查看。 Docker利用Linux桥接技术,在宿主机上虚拟出一个Docker网桥(docker0),启动容器时,根据docker0的网段分配给容器一个IP地址(Container-IP),同时docker0充当容器的默认网关。 宿主机上的容器共享同一个网桥,从而实现容器间的直接通信。 桥接模式(bridge模式)是Docker的默认网络模式。 当Docker进程启动时,创建docker0虚拟网桥。 宿主机上的容器连接到docker0,通过docker0与外部网络通信。 docker0分配IP给容器,设置docker0的IP作为容器默认网关。 iptables进行端口转发。 使用iptables -t nat -vnL可以查看规则。 桥接模式示意图如下:容器运行nginx,外部访问需要端口映射。 容器模式将新创建的容器与已存在的容器共享一个Network Namespace,不与宿主机共享。 新容器不创建网卡、IP等,而是共享指定容器的网络配置。 容器间可通过lo网卡设备通信。 主机模式下,容器共享宿主机的Network Namespace,不虚拟网卡、配置IP等,使用宿主机IP与外部通信,网络性能较好,但宿主机已用端口不可用,隔离性不佳。 使用none模式时,容器拥有独立的Network Namespace,但不进行网络配置,需手动添加网卡、配置IP等。 容器只有lo回环网络,适合封闭网络场景,保证安全性。 应用场景:none模式示意图。 Linux内核支持通过ip netns命令管理Network Namespace。 ip netns命令允许创建、操作Namespace,通常需要sudo权限。 命令帮助信息通过ip netns help查看。 创建命名空间ns0,新Namespace出现在/var/run/netns目录下,若已有同名Namespace,创建失败。 每个Namespace拥有独立的网络资源,如网卡、路由表、iptables等。 ip netns exec可以在Namespace中执行命令,如查看网卡信息。 启用lo回环网卡。 通过veth对设备进行转移,仅支持veth设备。 veth对实现不同Namespace间通信,将两端连接。 创建veth对并启用,配置IP,实现Namespace间通信。 桥接模式配置时,使用--network bridge等效于不指定网络模式。 none模式配置示例:容器拥有独立Namespace,需手动配置网络。 容器模式示例:启动两个容器,共享网络但隔离文件系统。 主机模式配置示例:直接使用宿主机网络,容器间隔离文件系统。 容器常用操作:查看主机名、指定DNS、映射主机名到IP、开放端口。 使用-p选项将容器端口映射到宿主机,实现外部访问容器应用。 格式为端口或范围,动态端口由系统分配。 使用docker port命令查看映射结果。 将容器端口映射到指定IP的随机端口。 修改/etc/docker/配置文件自定义docker0桥属性。 使用-docker选项指定控制主机创建容器。 创建自定义桥,与docker0不同。 使用自定义桥创建容器。 与默认bridge桥创建容器对比。