注:本文所有操作在centos8环境下进行!
一.容器网络管理
1.容器网络概述
容器网络主要用于容器与容器、容器与外网、容器与宿主机之间的通信及互联。宿主机接通外网,再与容器之间搭建网桥,使容器与宿主机网络联通,以达到容器连接外网的目的,如图所示。
用户可以创建一个或多个网络,一个容器可以加入一个或多个网络。同一个网络中的容器可以相互通信,不同网络中的容器相互隔离。在创建容器之前,用户可以先创建网络,然后再将容器添加到网络,即创建容器与创建网络是分开的。
Docker的本地网络实现是利用了Linux的Network Namespace和虚拟网络设备(主要是Virtual Ethernet Pair),在本地主机和容器内分别创建一个虚拟接口,并使它们彼此连通。Docker使用Linux的Namespace技术来进行资源隔离,例如,PID Namespace隔离进程、Mount Namespace隔离文件系统、Network Namespace隔离网络等。Network Namespace为容器提供了独立的网络环境。 Virtual Ethernet Pair简称VETH Pair,是一对端口,所有从这对端口进入的数据包都将从另一端出来,反之也是一样。
2.查看容器网络
用户要对容器网络进行配置,首先要熟练掌握命令,下面详细介绍容器网络管理命令。
查看容器网络的命令格式为:
[root@Docker ~]# docker network ls [OPTIONS]
参数介绍如下。
-f, --filter filter
过滤条件。
--format string
格式化打印结果。
--no-trunc
不缩略显示。
-q, --quiet
只显示网络对象的ID。
首先,查看所有容器网络。
[root@Docker ~]# docker network ls
如以上示例所示,容器网络也有其固定的ID号,DRIVER表示容器网络的驱动程序,SCOPE表示容器网络的作用域。默认情况下,容器创建完成后,会自动创建bridge、host、none三种网络模式。
接着,通过在命令中添加过滤条件查看容器网络。
[root@Docker ~]# docker network ls -f 'driver=host'
以上示例通过-f参数添加了'driver=host'过滤条件,成功过滤出了host网络。
通常Docker所显示的容器ID号、镜像ID号等都是通过缩略之后的结果,只要在命令中添加对应的参数即可显示完整ID号。通过在命令中添加参数,以不缩略的形式列出所有容器网络。
[root@Docker ~]# docker network ls --no-trunc
以上示例在命令中添加了--no-trunc参数,以不缩略的形式列出了所有容器网络。
最后,通过在命令中添加参数,列出所有网络的ID号。
[root@Docker ~]# docker network ls -q
以上示例在命令中添加了-q参数,列出了所有容器网络的ID号。
3.创建容器网络
创建网络的命令格式为:
[root@Docker ~]# docker network create [OPTIONS] NETWORK
参数介绍如下。
-d, --driver string
指定网络模式(默认为bridge)。
--subnet strings
指定子网网段。
--ip-range strings
指定容器的IP地址范围,格式同subnet参数。
--gateway strings
子网的IPV4或IPV6网关
创建一个容器网络,并指定它的网络模式。
[root@Docker ~]# docker network create -d bridge test-bridge
[root@Docker ~]# docker network ls
以上示例创建了一个命名为test-bridge的新容器网络,并指定它的网络模式为bridge网络。其余网络属性配置方式与之相同,这里不再赘述。
4.删除容器网络
删除容器网络的操作,在生产环境中建议再三确认之后再执行删除操作。删除容器网络与删除容器同样都需要在命令中添加rm参数。
删除容器网络的命令格式为:
[root@Docker ~]# docker network rm NETWORK...
首先,查看是否有需要删除的容器网络。
[root@Docker ~]# docker network ls
接着,将需要删除的容器网络进行删除。
[root@Docker ~]# docker network rm test-bridge
最后,查看容器网络是否被删除。
[root@Docker ~]# docker network ls
从以上示例中,可以看到容器网络test-bridge已经成功删除。
5.容器网络详情信息
查看容器网络详细信息的命令格式为:
[root@Docker ~]# docker network inspect [OPTIONS]
参数介绍如下。
-f, --format string
使用给定的模板格式化输出。
[root@Docker ~]# docker network inspect none
以上示例查看了none网络的详细信息,包括容器网络名称、容器网络ID容器网络创建时间等。
6.配置容器网络
配置容器网络就是为用户创建的容器添加网络配置,只需要在运行容器的命令中添加指定的网络参数。
配置容器网络的命令格式为:
[root@Docker ~]# docker run/create --network NETWORK
示例代码如下:
[root@Docker ~]# docker run -it -d \
> --network=host \
> docker.io/centos /bin/bash
以上示例通过在运行容器中添加--network参数,指定了容器的host网络模式。其中,反斜杠“\”表示命令没有输入完,上下两行为同一条命令,这种命令输入方式适合在输入长命令时使用。
查看容器信息,验证该容器网络是否为host模式。
[root@Docker ~]# docker inspect e2 | grep NetworkMode
以上示例通过docker inspect命令中添加grep参数过滤出了该容器的网络模式为host的信息。
7.容器网络连接与断开
容器网络连接与断开的命令格式为:
[root@Docker ~]# docker network connect [OPTTONS] NETWORK CONTAINER
[root@Docker ~]# docker network disconnect [OPTTONS] NETWORK CONTAINER
通过示例讲解容器网络的连接与断开,首先创建一个容器。
[root@Docker ~]# docker run -it -d \
> --network=host \
> docker.io/centos /bin/bash
以上示例运行了一个连接host网络的容器。
然后将该容器与host网络断开。
[root@Docker ~]# docker network ls
[root@Docker ~]# docker stop 6b96
[root@Docker ~]# docker network disconnect 08b0 6b96
以上示例使该容器与host网络断开。在命令中使用ID号即可,并且断开网络之前需要先关闭该容器。
下面再次执行断开网络命令,观察执行结果。
[root@Docker ~]# docker network disconnect 08b0 6b96
以上示例中,再次执行断开命令时发生报错,提示网络已断开。
下面将该容器添加到none网络中。
[root@Docker ~]# docker network connect bce9 6b96
二.none网络
顾名思义,none网络就是什么都没有的网络。在这种模式下,Docker容器网络拥有自己的网络命名空间,但并不为Docker容器进行任何网络配置。也就是说,这个模式下的容器除了本地环回接口,没有其他任何网卡、IP、路由等信息,如图所示。
没有网络配置的情况下,Docker开发者才能在此基础上做其他无限多可能的网络定制开发。用户可以自己为Docker容器添加网卡、配置IP地址等。这也正体现了Docker开放的设计理念。
下面使用默认网络模式创建一个BusyBox容器。
[root@Docker ~]# docker run --rm -it \
> --name test-default \
> docker.io/busybox
以上示例运行了一个被命名为test-default的BusyBox容器,并且此时已进入容器。
下面在容器终端中查看容器IP地址。
/ # ip a
从以上示例中可以看到,Docker为容器分配了IP地址。
下面通过ping命令测试容器网络是否能够联通外网。
/ # ping -c 3 www.mobiletrain.org
以上示例中,通过ping协议连通了外网,说明容器能够正常上网。
作为对比验证,再运行一个BusyBox容器,将网络设置为none模式。
[root@Docker ~]# docker run -it \
> --name test-none \
> --network=none docker.io/busybox
/ # ip a
/ # ping -c 3 www.mobiletrain.org
通过以上示例的对比验证,可以很清晰地理解Docker容器none网络就是没有网络。没有网络意味着安全性非常高,这样的网络模式通常可以用在一些对安全性要求较高,并且不需要联网的应用中,如用来产生随机密码的应用。
三.host网络
一个Docker容器一般会被分配一个独立的网络命名空间,但如果启动容器时选择了host模式,那么这个容器将不会分配一个独立的网络命名空间,而是和宿主机共享同一个网络命名空间。容器将使用宿主机的IP地址和端口号,如图所示。
下面在宿主机上运行一个网络模式为host的Web应用容器。
[root@Docker ~]# docker run -it -d \
> --name test-host \
> --network=host docker.io/nginx
上述示例运行了一个命名为test-host的Nginx容器,并指定网络模式为host,使其在后台运行。
下面查看容器信息。
[root@Docker ~]# docker inspect test-host
从以上示例中,可以看出网络模式为host。
下面再查看宿主机的80端口状态。
[root@Docker ~]# ss -anptu | grep 80
从以上示例中可以看出80端口被Nginx进程占用。创建容器时并没有指定端口映射,容器默认使用了宿主机的80端口,证明在host模式下宿主机与容器共用端口。
下面通过curl工具测试容器网站是否能够被访问。
[root@Docker ~]# curl -I 192.168.88.141
(ip地址为虚拟机ip地址)
四.bridge网络
在bridge模式下,Docker守护进程创建了一个虚拟以太网桥Docker0,附加在其上的网卡之间能自动转发数据包。默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0接口,另一个接口veth放置在宿主机的命名空间中,从而将宿主机上的所有容器都连接到这个内部网络上。同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器。如图所示。
下面通过brctl show命令可以查看容器网桥信息,在这之前需要安装网桥工具管理包,否则命令不生效。
此处演示安装包安装。
bridge-utils-1.6 源码下载。
wget https://mirrors.edge.kernel.org/pub/linux/utils/net/bridge-utils/bridge-utils-1.6.tar.xz
解压安装包。
tar -xvf bridge-utils-1.6.tar.xz
进入bridge-utils目录并使用 autoconf 工具生成配置文件。
[root@Docker ~]# cd bridge-utils-1.6
[root@Docker bridge-utils-1.6]# ls
[root@Docker bridge-utils-1.6]# autoconf
安装GCC软件套件并配置,生成makefile文件。
[root@Docker bridge-utils-1.6]# yum install gcc
[root@Docker bridge-utils-1.6]# ./configure
编译与安装。
[root@Docker bridge-utils-1.6]# make
[root@Docker bridge-utils-1.6]# sudo make install
安装完成之后,即可查看容器网桥信息。
[root@Docker ~]# brctl show
下面运行一个网络模式为bridge的容器。
[root@Docker ~]# docker run -it -d \
> --name test-nginx \
> --network=bridge \
> -p 8000:80 docker.io/nginx
以上示例在后台运行了一个命名为test-nginx的Nginx容器,并指定它的网络模式为bridge,将宿主机的8000端口映射到了容器的80端口。
下面接着查看容器网桥信息。
[root@Docker ~]# brctl show
从以上示例中可以看到,网桥Docker0上挂载了网络接口,vethaaf8a5e就是新创建的Nginx容器的虚拟网卡,名称以veth开头。
下面运行一个BusyBox容器,并设置网络模式为bridge,查看其网卡信息。
[root@Docker ~]# docker run -it \
> --name test-busybox \
> --network=bridge docker.io/busybox
[root@Docker ~]# brctl show
上述示例中,veth70a4bee就是BusyBox容器的虚拟网卡,名称同样以veth开头。
Docker采用NAT(Network Address Translation,网络地址转换)方式,将容器内部服务监听的端口与宿主机的某一个端口进行映射,使宿主机以外的网络可以将网络报文发送至容器内部。访问容器时,需要访问宿主机的IP及端口。因为增加了网络层,所以会影响网络的传输效率,如图所示。
在同一个服务器中,可能运行着多个业务,若这些业务都使用默认端口将会产生冲突,这时就需要容器映射不同的端口。
下面在宿主机中安装Apache服务。
[root@Docker ~]# yum -y install httpd
安装完成之后,启动Apache服务。
[root@Docker ~]# systemctl start httpd
以上示例在宿主机中启动了一个Apache服务。
下面通过查看端口的形式验证Apache是否正常运行。
[root@Docker ~]# ss -anptu | grep 80
以上示例查看宿主机80端口,可以看到80端口被Apache占用,服务正常运行。
下面创建一个Nginx容器,并配置端口映射。
[root@Docker ~]# docker run -d \
> --name test-nginx \
> -p 8000:80 docker.io/nginx
以上示例在后台运行了一个命名为test-nginx的Nginx容器,并将容器80端口映射到宿主机的8000端口。
下面测试用户通过宿主机的8000端口是否能够访问容器中的Nginx服务。
[root@Docker ~]# curl -I 192.168.88.141:8000
注:ip地址为虚拟机ip地址
从以上示例可以看出,通过宿主机的8000端口可以正常访问Nginx容器。
下面再访问宿主机的Apache服务。
[root@Docker ~]# curl -I 192.168.88.141
从以上示例可以看出,通过宿主机80端口可以正常访问Apache服务。有了端口映射,容器与容器、容器与宿主机的业务就不会出现冲突,保证了业务都能够被正常访问。
五.container网络
container是容器网络中一种较为特殊的网络模式。这个模式指定新创建的容器和已经存在的容器共享一个网络命名空间,而不是和宿主机共享。新创建的容器没有自己的网卡、IP地址等,而是和一个指定的容器共享IP地址、端口号等。这两个容器之间不存在网络隔离,而这两个容器与宿主机以及其他容器之间存在网络隔离。如图所示。
下面搭建一个container网络模型并查看效果,首先创建一个普通容器。
[root@Docker ~]# docker run -it --name test1 docker.io/busybox
以上示例创建了一个被命名为test1的BusyBox容器,此时该容器的网络模式默认为bridge。
创建完成后,在容器终端中查看容器IP信息。
/ # ip a
/ # exit
以上示例中,通过查看容器IP信息得知该容器IP地址为172.17.0.3。
下面创建一个网络模式为container的容器。
[root@Docker ~]# docker run -it --name test-container --network=container:test1 docker.io/busybox
注:上面已经退出test1容器,需要执行docker start 指令启动test1容器
以上示例创建了一个被命名为test-container的BusyBox容器,它与先前的test1容器共享网络空间。其中,在配置container网络时,需要添加与新容器共享网络命名空间的容器名称。
下面在test-container容器终端中查看其IP信息。
/ # ip a
从以上示例中可以看到,容器test-container与容器test1的IP地址是一样的,但不排除容器test1在创建之后自动崩溃,新的容器test-container沿用了它的IP地址的可能。
下面在宿主机终端中查看容器信息。
[root@Docker ~]# docker ps
以上示例说明这两个容器已经进行了网络空间共享。此时,两个容器之间已经可以进行通信。