1.3 Docker网络与数据卷

Docker网络


  • Overlay Network

Overlay 在网络技术领域,指的是一种网络架构上叠加的虚拟化技术模式,其大体框架是对基础网络不进行大规模修改的条件下,实现应用在网络上的承载,并能与其它网络业务分离,并且以基于IP的基础网络技术为主。Overlay 技术是在现有的物理网络之上构建一个虚拟网络,上层应用只与虚拟网络相关

在以往IT建设中,硬件服务器上运行的是虚拟层的计算,物理网络为了与虚拟服务器对接,需要网络自己进行调整,以便和新的计算层对接。Overlay 是在传统网络上虚拟出一个虚拟网络来,传统网络不需要在做任何适配,这样物理层网络只对应物理层的计算(物理机、虚拟化层管理网),虚拟的网络只对应虚拟计算(虚拟机的业务IP)

  • 使用网络

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。

当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。

bridge

bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。

当 Docker server 启动时,会在主机上创建一个名为 docker0 的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配 IP 了,Docke r会从 RFC918 所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给 docker0,连接到 docker0 的容器就从这个子网中选择一个未占用的IP使用。如一般 Docke r会使用 172.17.0.0/16 这个网段,并将 172.17.42.1/16 分配给 docker0 网桥 

bridge工作流程

在主机上创建一对虚拟网卡 veth pair 设备。veth 设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth 设备常用来连接两个网络设备

Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为 eth0。另一端放在主机中,以 veth******* 这样的名字命名,并将这个网络设备加入到 docker0 网桥中,可以通过 brctl show 命令查看

[root@CentOS74 ~]#brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.024220c0a37a	no		vethbc2d1dc
							vethcf47b7e

从 docker0 子网中分配一个IP给容器使用,并设置 docker0 的 IP 地址为容器的默认网关

在物理机上使用 ip 命令调用内核参数,模拟 docker 网络中 brigde 的工作流程

[root@CentOS174 ~]# ip netns add testns   #新增一个Net名称空间
[root@CentOS174 ~]# ip netns list
testns
[root@CentOS174 ~]# ip link add name veth10 type veth peer name veth01  #新键一对虚拟网卡
[root@CentOS174 ~]# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:3d:70:fc brd ff:ff:ff:ff:ff:ff
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:3d:70:06 brd ff:ff:ff:ff:ff:ff
4: veth01@veth10: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000   #虚拟网卡总是相会对应
    link/ether 22:d3:7d:fc:43:bb brd ff:ff:ff:ff:ff:ff
5: veth10@veth01: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 6a:3e:84:a3:9c:af brd ff:ff:ff:ff:ff:ff
[root@CentOS174 ~]# ip link set veth10 netns testns  #将虚拟网卡中的一块分配给指定Net名称空间
[root@CentOS174 ~]# ip link set veth01 up  #启动主机一端的网卡
[root@CentOS174 ~]# ip addr add 172.17.0.1/16 dev veth01  #为其配置ip地址
[root@CentOS174 ~]# ip addr show veth01 
4: veth01@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 22:d3:7d:fc:43:bb brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.1/16 scope global veth01
       valid_lft forever preferred_lft forever
    inet6 fe80::20d3:7dff:fefc:43bb/64 scope link 
       valid_lft forever preferred_lft forever
[root@CentOS174 ~]# ip netns exec testns ip link set dev veth10 up  #启动testns空间中一端的网卡
[root@CentOS174 ~]# ip netns exec testns ip addr add 172.17.0.2/16 dev veth10  #为期配置ip地址
       valid_lft forever preferred_lft forever
[root@CentOS174 ~]# ip netns exec testns ip a show veth10
5: veth10@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 6a:3e:84:a3:9c:af brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 scope global veth10
       valid_lft forever preferred_lft forever
    inet6 fe80::683e:84ff:fea3:9caf/64 scope link 
       valid_lft forever preferred_lft forever

在创建容器时,使用 --network bridge 指定使用 bridge 模式网络,并使用 -p 选项暴露容器的指定端口,当需要暴露的端口有多个时,可以多次使用 -p 选项

[root@CentOS74 ~]# docker run --name nettest -d --rm --network bridge -p 80 miriam:CentOS-Nginx

使用 ss -ntl 或者 iptables -t nat -vnL 亦或者 docker port 容器名 查看本地的端口映射

-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32769 -j DNAT --to-destination 172.17.0.3:80

[root@CentOS74 ~]# docker port nettest 
80/tcp -> 0.0.0.0:32769

也可以映射本机的指定端口,或者指定地址的指定端口,或者指定地址的动态端口

[root@CentOS74 ~]# docker run --name nettest -d --rm --network bridge -p 80:80 miriam:CentOS-Nginx 
b09da5fb40aaf3921a0c6707f030d1eaa3b81e2f35873e6284d188f3bf8508df
[root@CentOS74 ~]# docker port nettest 
80/tcp -> 0.0.0.0:80

[root@CentOS74 ~]# docker run --name nettest -d --rm --network bridge -p 192.168.30.74:80:80 miriam:CentOS-Nginx 
aa447e2264905ac36b7a84dfa96c1e06e56c1118943163fd05170542460b6749
[root@CentOS74 ~]# docker port nettest 
80/tcp -> 192.168.30.74:80

使用 -P 选项暴露镜像文件中声明的监听端口

[root@CentOS74 ~]# docker run --name nettest -d --rm --network bridge -P miriam:CentOS-Nginx 
888f6602e968eda1a32f269dc7f0856b253b74114bc8a0d1e7f66384517cab47

Host

当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.10.101.105:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。

在创建容器时,使用 --network host 指定使用 host 模式网络

[root@CentOS74 ~]# docker run --name nettest -d --rm --network host miriam:CentOS-Nginx 
bf46888a3079997e35aa919d7de9fe5127a8d8a30a23062dc02e147fc003a459
[root@CentOS74 ~]#⮀⮀ss -ntl
State       Recv-Q Send-Q                                                 Local Address:Port                                                                Peer Address:Port              
LISTEN      0      128                                                                *:80                                                                             *:*                  
LISTEN      0      128                                                                *:22                                                                             *:*                  
LISTEN      0      100                                                        127.0.0.1:25                                                                             *:*                  
LISTEN      0      128                                                     172.20.116.3:10010                                                                          *:*                  
LISTEN      0      128                                                               :::80                                                                            :::*                  
LISTEN      0      128                                                               :::22                                                                            :::*                  
LISTEN      0      100                                                              ::1:25                                                                            :::*                  

container

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

[root@CentOS74 ~]# docker run --name netbbox -it --rm --network container:test jiangbowen/httpbbox:v0.1-1

Null

这个模式和前两个不同。在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。

在创建容器时,使用 --network none 指定使用 null 模式网络

  • 修改网络

配置文件修改daemon属性

当需要修改 docker0 桥使用的 ip 地址,则需要修改 /etc/docker/daemon.json

其中有许多配置项,可以在 Docler 配置文件 中查看具体配置

{
	"api-cors-header": "", 
	"authorization-plugins": [],
	"bip": "",
	"bridge": "",
	"cgroup-parent": "",
	"cluster-store": "",
	"cluster-store-opts": {},
	"cluster-advertise": "",
	"debug": true, #启用debug的模式,启用后,可以看到很多的启动信息。默认 false
	"default-gateway": "",
	"default-gateway-v6": "",
	"default-runtime": "runc",
	"default-ulimits": {},
	"disable-legacy-registry": false,
	"dns": ["192.168.80.1"], // 设定容器DNS的地址,在容器的 /etc/resolv.conf 文件中可查看。
	"dns-opts": [], // 参考:Docker的启动参数
	"dns-search": [], // 参考:Docker的启动参数
	"exec-opts": [],
	"exec-root": "",
	"fixed-cidr": "",
	"fixed-cidr-v6": "",
	"graph": "/var/lib/docker", #已废弃,使用data-root代替
	"data-root": "/var/lib/docker", /*Docker运行时使用的根路径,默认/var/lib/docker*/
	"group": "", #Unix套接字的属组,仅指/var/run/docker.sock 
	"hosts": [], #设置容器hosts
	"icc": false,
	"insecure-registries": [],
	"ip": "0.0.0.0",
	"iptables": false,
	"ipv6": false,
	"ip-forward": false, // 参考:Docker的启动参数
	"ip-masq": false,
	"labels": ["nodeName=node-121"], //参考:Docker的启动参数
	"live-restore": true,
	"log-driver": "",
	"log-level": "",
	"log-opts": {},
	"max-concurrent-downloads": 3,
	"max-concurrent-uploads": 5,
	"mtu": 0,
	"oom-score-adjust": -500,
	"pidfile": "", #Docker守护进程的PID文件
	"raw-logs": false,
	"registry-mirrors": ["xxxx"], //镜像加速的地址,增加后在 docker info 中可查看。
	"runtimes": {
		"runc": {
			"path": "runc"
		},
		"custom": {
			"path": "/usr/local/bin/my-runc-replacement",
			"runtimeArgs": ["--debug"]
		}
	},
	"selinux-enabled": false, #参考:Docker的启动参数
	"storage-driver": "",
	"storage-opts": [],
	"swarm-default-advertise-addr": "",
	"tls": true, #参考:Docker的启动参数
	"tlscacert": "", #参考:Docker的启动参数
	"tlscert": "", #参考:Docker的启动参数
	"tlskey": "", #参考:Docker的启动参数
	"tlsverify": true, #参考:Docker的启动参数
	"userland-proxy": false,
	"userns-remap": ""
}

其中修改网络配置中最重要的选项是 "bip": "" ,当修改此项后,其他的网络参数也将会自动根据其修改

[root@CentOS74 ~]# ip addr show docker0 
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:f9:9b:b7:50 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.1/24 brd 192.168.20.255 scope global docker0
       valid_lft forever preferred_lft forever

修改 hosts 选项使本地 Docker daemon 可以被外部主机通过网络连接

[root@CentOS74 ~]#⮀⮀cat /etc/docker/daemon.json 
{
    "registry-mirrors": ["https://xet4hxm8.mirror.aliyuncs.com"],
    "bip": "192.168.20.1/24",
    "default-gateway": "192.168.20.174",
    "dns": ["114.114.114.144","8.8.8.8"],
    "mtu": 1500,
    "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}

这时便可以使用 docker 的 -H 选项连接远程主机的 Docker daemon

创建自定义网络

使用 docker network create 命令创建新的 docker 网络

[root@CentOS74 ~]# docker network create -d "bridge" --subnet "192.168.10.0/24" --gateway "192.168.10.1" dcoker1
be7c49653f4d505a6daba179854dac551212a74a74472b3a5dfc5c9698204be0

创建完成后可以在创建容器时通过 --network 选项使用指定网络

[root@CentOS74 ~]# docker container run -it --rm --network dcoker1 jiangbowen/httpbbox:v0.1-1

当通主机上的两个 docker 网络进行通信时,则需要修改 iptables 的 filter 表中的 DOCKER-ISOLATION-STAGE-2 链,并打开内核中的路由转发

[root@CentOS74 ~]# iptables -R DOCKER-ISOLATION-STAGE-2 1 -o docker0 -j ACCEPT
[root@CentOS74 ~]# iptables -R DOCKER-ISOLATION-STAGE-2 2 -o docker0 -j ACCEPT
[root@CentOS74 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

数据卷


数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

    数据卷可以在容器之间共享和重用
    对数据卷的修改会立马生效
    对数据卷的更新,不会影响镜像
    卷会一直存在,直到没有容器使用

数据卷的使用,类似于 Linux 下对目录或文件进行 mount

  • 创建数据卷

绑定挂载卷

用户同时指定容器中目录与宿主机目录路径

[root@CentOS74 CentOS-Nginx]# echo "This is Host HomePage" > /usr/share/nginx/html/index.html
[root@CentOS74 CentOS-Nginx]# cat /usr/share/nginx/html/index.html
This is Host HomePage
[root@CentOS74 CentOS-Nginx]# docker container run -d -v /usr/share/nginx/html/index.html:/usr/share/nginx/html/index.html miriam:CentOS-Nginx 
68db5858815724fea05ebae4c77795db13b7e3d353587efcb0eaf702b72a6e71
[root@CentOS74 CentOS-Nginx]# curl http://192.168.20.2
This is Host HomePage

这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它。

注意:Dockerfile 中不支持这种用法,这是因为 Dockerfile 是为了移植和分享用的。然而,不同操作系统的路径格式不一样,所以目前还不能支持。

Docker管理卷

用户只用指定容器中的目录,而宿主机上的目录则由 Docker 自动在默认路径下创建。但是当第二次使用容器时,为了保证数据的持久性,则必须使用绑定挂载卷的模式启动容器

使用 Docker 管理卷的模式挂载数据卷

[root@CentOS74 CentOS-Nginx]# docker container run -d -v /usr/share/nginx/html/ miriam:CentOS-Nginx 
7ff6531e7e9248b9e9adb9ab8a10bbb415f7d957e4a43a0545a31337a3f051eb

 容器创建后,通过 docker container inspect 容器名 查看 Mounts 段记录的本地文件路径

        "Mounts": [
            {
                "Type": "volume",
                "Name": "51b3120f4d9d8787ceefdfea14f8971a4d11cc021d3c4e4889c6db98b2394c45",
                "Source": "/var/lib/docker/volumes/51b3120f4d9d8787ceefdfea14f8971a4d11cc021d3c4e4889c6db98b2394c45/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }

在宿主机上修改数据卷中的文件,在容器中查看

[root@CentOS74 share]# curl http://192.168.20.2
This is Miriam HomePage
[root@CentOS74 share]# curl http://192.168.20.2
This is Miriam VOLUME

注意:如果直接挂载一个文件,很多文件编辑工具,可能会造成文件 inode 的改变,从 Docker 1.1.0起,这会导致报错误信息。所以最简单的办法就直接挂载文件的父目录。

Docker 挂载数据卷的默认权限是读写,用户也可以通过 :ro 指定为只读。

[root@CentOS74 ~]# docker container run -d -v /data/:/usr/share/nginx/html/:ro miriam:CentOS-Nginx 
bc537c2574f567d45806b85465f8cae9df199a669caa669f68a7ca5782e0de6f
  • 数据卷容器

如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。

数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。

使用 --volumes-from 容器名 来共享指定容器的数据卷配置

[root@CentOS74 ~]# docker container run -d --rm --volumes-from tender_wozniak miriam:CentOS-Nginx 
2833be95ae1cd8be2ab6012affef7fdd0a45d847fbb1a7eb567d8820df24dfe1

猜你喜欢

转载自blog.csdn.net/M30_Miriam/article/details/81367872
1.3
今日推荐