Docker网络详解

Docker网路基础理论

docker使用Linux桥接网卡,在宿主机虚拟一个docker容器网桥(docker0),docker启动一个容器时会根据docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网络网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。

如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过-p或-P参数来启用,访问容器的时候就通过​​宿主机IP:容器端口​​访问容器。

Docker网络模式

Docker网络模式

配置

说明

host模式

–net=host

容器和宿主机共享​​Network namespace​​。

容器将不会虚拟出自己的网卡,配置自己的IP 等,而是使用宿主机的IP和端口。

container模式

–net=container:NAME_or_ID

容器和另外一个容器共享​​Network namespace​​。

kubernetes中的pod就是多个容器共享一个Network namespace。

创建的容器不会创建自己的网卡,配置自己的 IP, 而是和​​一个指定的容器共享IP、端口范围​​。

none模式

–net=none

容器有独立的Network namespace,并没有对其进行任何网络设置,如分配veth pair和网桥连接,配置IP等。

​该模式关闭了容器的网络功能。​

bridge模式

–net=bridge

(默认模式)。此模式会为每一个容器分配、设置IP等,并将容器连接到一个​​docker0虚拟网桥​​​,通过​​docker0网桥​​​以及​​Iptable nat​​表配置与宿主机通信

Macvlan

network

容器具备Mac地址,使其显示为网络上的物理 设备

Overlay

(覆盖网络): 利用VXLAN实现的bridge模式

bridge模式

默认的网络模式。bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的,但容器通过宿主机的NAT规则后可以访问外网。

Bridge 桥接模式的实现步骤

  • Docker Daemon利用veth pair技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和veth1。而veth pair技术的特性可以保证无论哪一个veth接收到网络报文,都会将报文传输给另一方。
  • Docker Daemon将veth0附加到Docker Daemon创建的docker0网桥上。保证宿主机的网络报 文可以发往veth0;
  • Docker Daemon 将veth1添加到Docker Container所属的namespace下,并被改名为eth0。 如此一来,保证宿主机的网络报文若发往veth0则立即会被eth0接收,实现宿主机到Docker Container网络的联通性;同时也保证Docker Container单独使用eth0,实现容器网络环境的隔离性。

Bridge桥接模式的缺陷

Docker Container不具有一个公有IP,即和宿主机eth0不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。

注意

eth设备是成双成对出现的,一端是容器内部命名为eth0,一端是加入到网桥并命名的veth(通常命名为veth),它们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据通信。

Host网络模式

host模式相当于Vmware中的NAT模式,与宿主机在同一个网络中,但​​没有独立IP地址​​。

启动容器使用host模式,容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。

容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。除此之外容器的其他方面,比如文件系统、进程列表等还是和宿主机隔离

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,​​host最大的优势就是网络性能比较好​​,docker host上已经使用的端口就不能再用了,网络的隔离性不好。

host网络模式需要在容器创建时指定–network=host

host模式是bridge桥接模式很好的补充。采用host模式的Docker Container,可以直接使用宿主机的IP地址与外界进行通信,若宿主机的eth0是一个公有IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换。

host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

Host网络模式的缺陷

使用Host模式的容器不再拥有隔离、独立的网络环境。虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用; 另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以bridge网络模式容器的端口映射。

Container网络模式

一种特殊host网络模式, ontainer网络模式是Docker中一种较为特别的网络的模式。在容器创建时使用– network=container:vm1指定。(vm1指定的是运行的容器名)处于这个模式下的 Docker 容器会共享一个网络环境,这样两个容器之间可以使用localhost高效快速通信。

Container网络模式的缺陷

Container网络模式没有改善容器与宿主机以外世界通信的情况(和桥接模式一样,不能连接宿主机以外的其他设备)。

这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。 同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信

none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。​​Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。​

这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过-- network=none来指定。​​这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。​

网络基本用法

作为演示,使用nginx景象进行

镜像的相关操作

  • 拉取镜像
docker pull nginx:1.19.3-alpine
  • 运行镜像
docker run -itd --name nginx1  nginx:1.19.3-alpine
  • 容器创建时IP地址的分配

使用​​docker network inspect bridge​​效果如下图

全网最详细的Docker网络教程详解_Docker

docker容器创建流程

  • 创建一对虚拟接口/网卡,也就是veth pair,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 vetha596da4;
  • 容器一端放到新容器中,并修改名字作为 eth0,这个网卡/接口只在容器的名字空间可见;
  • 从网桥可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 vetha596da4。
  • 容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 如果不指定--network,创建的容器默认都会挂到 docker0 上,使用本地主机上 docker0 接口的 IP 作为 所有容器的默认网关。
  • 进入容器查看网络地址
第一种方式:
docker exec -it nginx1 sh

ip a

第二种方式:
docker exec -it nginx1 ip a

安装brctl

yum install -y bridge-utils

运行brctl

brctl show

容器连接图

全网最详细的Docker网络教程详解_Docker_02

多容器之间通讯

docker run -itd --name nginx1  nginx:1.19.3-alpine

docker run -itd --name nginx2 nginx:1.19.3-alpine

docker network inspect bridge

docker exec -it nginx1 sh

ping 172.17.0.2

docker exec -it nginx2 sh

ping 172.17.0.2

ping www.baidu.com

ping nginx1

重启容器IP地址会发生变化

docker stop nginx1 nginx2

先启动nginx2,在启动
nginx1 docker start nginx2
docker start nginx1
docker network inspect bridge

解决容器IP地址变化(新建bridge网络)

docker network create -d bridge test-bridge

上面命令参数-d 是指DRIVER的类型,后面的test-bridge是network的自定义名称,这个和docker0是类似的。下面开始介绍,如何把容器连接到test-bridge这个网络。

启动一个nginx的容器nginx3,并通过参数network connect来连接lagou-bridge网络。在启动容器 nginx3之前,我们查看目前还没有容器连接到了test-bridge这个网络上。

brctl show

docker network ls

docker network inspect test-bridge

docker run -itd --name nginx3 --network test-bridge nginx:1.19.3-alpine

brctl show

docker network inspect test-bridg
  • 把一个运行中容器连接到test-bridge网络
docker network connect test-bridge nginx2

docker network inspect test-bridge

docker exec -it nginx2 sh

ping nginx3
docker exec -it nginx3 sh
ping nginx2

none网络

启动一个ngnix的容器nginx1,并且连接到none网络。然后执行docker network inspect none,看看容器信息

docker run -itd --name nginx1 --network none  nginx:1.19.3-alpine

docker network inspect none

注意

容器使用none模式,是没有物理地址和IP地址。我们可以进入到nginx1容器里,执行ip a命令看 看。只有一个lo接口,没有其他网络接口,没有IP。也就是说,使用none模式,这个容器是不能被其他 容器访问。这种使用场景很少,只有项目安全性很高的功能才能使用到。

docker exec -it nginx1 sh

ip a

docker网络命令汇总

查看网络(docker network ls)

查看已经建立的网络对象

  • 语法
docker network ls [OPTIONS]
  • 常用参数-f
  • -q, --quiet 格式化打印结果 不缩略显示 只显示网络对象的ID
  • --filter filter 过滤条件(如 'driver=bridge’)
  • --format string
  • --no-trunc
  • 基本使用
docker network ls

docker network ls --no-trunc

docker network ls -f 'driver=host'

创建网络(docker network create)

创建新的网络对象

  • 语法
docker network create [OPTIONS] NETWORK
  • 常用参数
  • --driver string 指定网络的驱动(默认 "bridge")
  • --subnet strings 指定子网网段(如192.168.0.0/16、172.88.0.0/24)
    --ip-range strings 执行容器的IP范围,格式同subnet参数
  • --gateway strings 子网的IPv4 or IPv6网关,如(192.168.0.1)
  • 基本使用
docker network ls

docker network create -d bridge my-bridge

docker network ls

网络删除(docker network rm)

删除一个或多个网络

  • 语法
docker network rm NETWORK [NETWORK...]

查看网络详细信息(docker network inspect)

查看一个或多个网络的详细信息

  • 语法
docker network inspect [OPTIONS] NETWORK [NETWORK...]

docker inspect [OPTIONS] NETWORK [NETWORK...]
  • 常见参数
  • -f, --format string 根据format输出结果

使用网络(docker run –-network)

为启动的容器指定网络模式

  • 语法
docker run/create --network NETWORK

网络连接与断开(docker network connect/disconnect)

docker network connect/disconnect

  • 语法
docker network connect [OPTIONS] NETWORK CONTAINER

docker network disconnect [OPTIONS] NETWORK CONTAINER
  • 常见参数
  • -f, --force 强制断开连接(用于disconnect)

容器镜像设定固定ip

docker network create -d bridge --subnet=172.172.0.0/24  --gateway 172.172.0.1 network

172.172.0.0/24: 24代表子码掩码是255.255.255.0 172.172.0.0/16: 16 代表子码掩码

docker network ls

docker run -itd --name nginx3 -p 80:80 --net network --ip 172.172.0.10

nginx:1.19.3-alpine

--net mynetwork:选择存在的网络

--ip 172.172.0.10:给nginx分配固定的IP地址

docker network inspect network

docker stop nginx3

docker start nginx3

docker network inspect network

到此Docker网络相关的知识和语法就分享到这里。希望自己能够熟练使用docker