接上篇
第8-11章
12、基本架构
早期的docker是基于已经成熟的LXC(linux container)技术实现的.自0.9版本起,docker已经逐渐从LXC转移到新的libcontainer上,并且积极推动开放容器规范runc;
从OS功能上看,目前Docker底层依赖的核心技术主要包括linux操作系统的命名空间(name space), 控制组( cgroup ),联合文件系统( union file system 或 aufs )和linux网络虚拟化支持。
docker目前采用的是标准的C/S架构,client和service即可以运行在一台机器上,也可以在不同机器上通过socker和RESTful API来进行通信。
12.1、服务端
Docker Daemon一般在宿主机后台运行,作为服务端接受来自客户的请求,并处理这些请求 ( 创建、运行、分发容器)。
在设计上,docker Daemon 是一个模块化的任务,通过专门的engine模块来分发管理各个来自客户端的任务。
Docker服务器默认监听本地的套接字,只允许本地的root用户或docker用户组成员访问,可以通过-H 选项来修改监听的方式。
Host $ docker daemon -H IP:port 如 docker daemon -H 0.0.0.0:2222
Docker默认启动配置文件在/etc/default/docker
12.2、客户端
Docker客户端为用户提供一系列的可执行命令,用户用这些命令与Docker Daemon交互。用户使用的Dokcer可执行命令即为客户端程序,客户端发送命令后,等待服务端返回,一旦收到返回后,客户端立刻执行结束并退出,用户执行新的命令,需要再次调用客户端命令。
如果服务端没有监听在默认的地址,那么连接服务器的时候就需要指定服务端地址,假如服务器监听在1.1.1.1的tcp2345,只有通过-H指定正确的地址才能进行连接
docker -H tcp://1.1.1.1:2345 version 查看
13、命名空间
命名空间(namespace) 是linux内核的一个强大特性,利用这一特性,每个容器都可以拥有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统环境中一样,命名空间机制保证了容器之间彼此互不影响。
13.1、进程命名空间
Linux通过命名空间管理进程号,对于同一个进程( 即同一个task_struct),在不同的命名空间中,看到的进程号不相同,每个进程命名空间有一套自己的进程号管理方法,进程命名空间是一个父子关系的结构,子空间中的进程对父空间是可见的,新fork出的进程在父命名空间和子命名空间将分别有一个进程号来对应。
13.2、网络命名空间
如果有了pid命名空间,那么每个命名空间中的进程就可以相互隔离,但网络端口还是共享本地系统的端口,通过网络命名空间,可以实现网络隔离。
网络空间为进程提供了一个完全独立的网络协议栈的视图,包括网络设备接口,ipv4\ipv6协议栈,ip路由表,防火墙规划,sockets等,这样每个容器的网络都能隔离开来.
使用brctl工具就能看到桥接到宿主机docker0网桥上的虚拟网口
系统如果自带没有需要安装这个软件
yum -y install bridge-utils
13.3、IPC命名空间
容器中进程交互还是采用了Linux常见的进程间交互方法(ipc),包括了信号量、消息队列和共享内存等。pid namespace和IPC namespace 可以组合一起使用,同一个IPC命名空间内的进程可以彼此可见,允许进行交互,不同空间的进程则无法交互。
13.4、挂载命名空间
类似于chroot,将一个进程放到一个特定的目录执行,挂载命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间中的进程所看到的文件目录彼此隔离,可以查看 volume挂载信息。
13.5、UTS命名空间 (名称)
UTS (unix Time-sharing system)命名空间允许每个容器拥有独立的主机名和域名,从而可以虚拟出一个独立主机名和网络空间的环境,就跟网络上一台独立的主机一样。
默认情况下,Docker容器的主机名就是返回容器ID:
[root@dockers _data]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
046799493e9c gitlab/gitlab-ce "/assets/wrapper" 7 hours ago Up 7 hours (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:333->22/tcp git2
docker inspect -f '{{.Config.Hostname}}' git2
046799493e9c
13.6、用户命名空间
每个容器可以有不同的用户和组ID,也就是说可以在容器内使用特定的用户执行程序,而非本地系统上存在的用户
14、控制组(cgroup)
控制组主要用来对共享资源进行隔离、限制、审计等,只有能控制分配到容器的资源,才能避免多个容器同时运行时对宿主机系统的资源竞争。
具体来看控制组提供:
- 资源限制:可以将组设置为不超过设定内存的限制,比如:内存子系统可以为进程组设定一个内存使用上限,一旦进程组使用的内存达到限额再申请内存,就会发出 out of memory的警告, 也可以是CPU,硬盘等。
- 优先级: 通过优先级让一些组优先得到更多的资源。
- 资源审记:用来统计系统实际上把多少资源用到适合的目的上,可以使用cpuacct子系统记录某个进程组使用的CPU时间。
- 隔离:为组隔离命名空间,这样一个组不会看到另一个组的进程、网络连接和文件系统。
- 控制:挂起,恢复和重新启动等操作
安装完docker之后,用户可以在/sys/fs/cgroup/memory/docker/目录下看到对Docker组应用的各种限制值,包括, 目录是容器的各项限制
注意:也可以在启动容器的时候为每个容器指定资源的限制,例如使用 -c | --cpu-shares=[0]参数来调整cpu的权重,使用-m| --monry[=MEMORY]参数来调整容器使用内存的大小。
15、联合文件系统
联合文件系统(unionFS) 是一种轻量级的高性能分层文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,应用看到的是挂载的最终结果。
15.1、Docker存储
Docker目前通过插件化方式支持多种文件系统后端。如图所示。aufs支持为每一个成员目录设定只读,读写,或写出的权限,同时AUFS里有一个类似分层的概念,对只读权限的分支可以在逻辑上进行增量地修改。Docker镜像自身就是由多个文件层组成,每一层有唯一的编号(层ID).
15.2、多种文件系统比较
Docker目前支持的联合文件系统种类包括AUFS、OverlayFS、Btrfs、vfs、zfs和Device Mapper等。
- AUFS: 最早支持的文件系统,对Debian/Ubuntu支持好,虽然没有合并到 linux内核中,但成熟度很高;
- OverlayFS:类似于AUFS,性能会更好一些,已经合并到内核,未来会取代AUFS,但成熟度有待提高;
- Device mapper:红帽公司和Docker团队一起开发用于支持RHEL的文件系统,内核支持,性能略慢,成熟度高;
- btrfs:参考zfs等特性设计的文件系统,由linux社区开发,试图未来取代Device Mapper,成熟度有待提高;
- vfs:基于普通文件系统(ext、nfs等)的中间层抽象,性能差,比较占用空间,成熟度也一般;
- zfs:最初设计为solaris 10上的写时文件系统,拥有不少好的特性,但对linux支持还不够成熟。
总结:AUFS和Device mapper的应用最为广泛,支持也相对成熟,推荐生产环境考虑,长期来看,OverlaryFS将可能具有更好的特性。
16、网络模式
Docker的本地网络实现其实就是利用了linux上的网络命名空间和虚拟网络设备(特别是veth pair)。
在使用docker run 命令启动容器的时候 可以指定--net参数来指定容器的配置
网络配置可选值 bridge、none、containrer、host和用户定义的网络
- --net=bridge:默认值,在docker网桥docker0上为容器创建新的网络栈;
- --net=none:让Docker将新容器放到隔离的网络栈中,但是不进行网络配置,之后用户可以自行进行配置 。
- --net=container:NAME_OR_ID: 让Docker将新建容器的进程放到一个已存在容器的网络栈中,\
新容器进程有自己 的文件系统、进程列表和资源限制,但是会和已存在的容器共享IP地址和端口等网络资源 ,两者进程 可以直接通过LO环回接口通信。 - --net=host:告诉Docker不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络,此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。\
容器进程可以和主机其它root进程一样打开低范围内的端口,可以访问本地网络服务,比如D-bus,如果进一步使用 --privileged=true参数,容器甚至会被允许直接配置主机的网络栈。 - --net=user_defined_network:用户自行用network命令创建一个网络,通过这种方式将容器连接到指定的已创建网络上去。
使用 docker network create networkname 可以创建一个新的网络 docker network ls 查看 docker network rm networkname 删除网络
17、配置私有仓库
17.1、安装Docker Registry
目前docker registry最新工具为2.0系列版本,这一版本与一些类库、工具一起被打包为负责容器内容分发的工具集:docker Distribution,目前其核心功能组件仍为负责镜像仓库的管理。
17.1.1、基于容器的运行方式
docker run -dit -p 5000:5000 --restart=always --name registry registry
使用docker inspect查看详细配置
"Cmd": [ 配置文件目录
"/etc/docker/registry/config.yml"
],
"ArgsEscaped": true,
"Image": "registry",
"Volumes": { 保存仓库的位置
"/var/lib/registry": {}
},
"WorkingDir": "",
"Entrypoint": [
"/entrypoint.sh"
],
[root@dockers ~]# docker exec -it df5757d25854 cat /etc/docker/registry/config.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
配置 文件目录及保存仓库位置应当持久化至本地
[root@dockers registry]# docker volume create registry
文件挂载使用-v比较方便,目录可以使用--mount
[root@dockers registry]# docker run -dit --name registry2 -v /root/registry/config.yml:/etc/docker/registry/config.yml --mount source=registry,target=/var/lib/registry registry
b6569571613eb1de01dc43a4c18c948784d7721cbbfb6a38e5067e5c47c8cb75
[root@dockers registry]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6569571613e registry "/entrypoint.sh /etc…" 5 seconds ago Up 2 seconds 5000/tcp registry2
17.1.2、本地安装运行
先安装golang跟git环境,此次安装是在另外一台机器上
yum -y install golang git
docker×××地址 docker distibution分发工具包
https://github.com/docker/distribution
git clone源码
git clone https://github.com/docker/distribution.git
迅雷或其它方式下载
https://codeload.github.com/docker/distribution/zip/master
创建配置文件目录
mkdir /etc/docker/registry -pv
当前目录解压distribution-master.zip
cd distribution-master
复制配置文件
cp cmd/registry/config-dev.yml /etc/docker/registry/config.yml
仓库目录
mkdir /var/lib/registry
注意: 一定要定义GOPATH环境变量 比如
# vim /etc/profile.d/go.sh
export GOPATH=/go
export PATH=$GOPATH:$PATH
# source /etc/profile.d/go.sh
安装
[root@do2 distribution-master]# make --prefix=/go clean binaries
安装的时候报错信息
cannot find package "github.com/docker/distribution/registry/auth/htpasswd" in any of:
/usr/lib/golang/src/github.com/docker/distribution/registry/auth/htpasswd (from $GOROOT)
解决办法
[root@do2 ~]# mv distribution-master /go/src/github.com/docker/
[root@do2 ~]# cd !$
cd /go/src/github.com/docker/
[root@do2 docker]# mv distribution-master/ distribution
[root@do2 distribution]# pwd
/go/src/github.com/docker/distribution
然后再编译
[root@do2 distribution]# make prefix=/go clean binaries
+ clean
fatal: Not a git repository (or any of the parent directories): .git
+ /go/src/github.com/docker/distribution/bin/registry
fatal: Not a git repository (or any of the parent directories): .git
+ /go/src/github.com/docker/distribution/bin/digest
fatal: Not a git repository (or any of the parent directories): .git
+ /go/src/github.com/docker/distribution/bin/registry-api-descriptor-template
+ binaries
编译成功启动
[root@do2 distribution]# ./bin/registry serve /etc/docker/registry/config.yml
INFO[0000] debug server listening :5001
# 检查服务是否成功开启
curl -i 127.0.0.1:5000
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Tue, 10 Apr 2018 22:08:36 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
## docker 服务器上操作
[root@dockers registry]# docker push 192.168.9.223:5000/v2/sshd:v2
The push refers to repository [192.168.9.223:5000/v2/sshd]
An image does not exist locally with the tag: 192.168.9.223:5000/v2/sshd
[root@dockers registry]# docker push 192.168.9.223:5000/sshd:v2
The push refers to repository [192.168.9.223:5000/sshd]
Get https://192.168.9.223:5000/v2/: http: server gave HTTP response to HTTPS client
增加这个地址
[root@dockers registry]# vim /etc/docker/daemon.json
{
"insecure-registries":[
"192.168.9.223:5000"
]
}
# 上传成功
# docker push 192.168.9.223:5000/sshd:v3
The push refers to repository [192.168.9.223:5000/sshd]
9b7093b64bd7: Layer already exists
68d4a84c343f: Layer already exists
71a8af6570d5: Layer already exists
b03095563b79: Layer already exists
v3: digest: sha256:46d7064f74b2fd47be7014f02e81d9e96bdafb1a07bc31dccc5d912e8f26c400 size: 1154
# 下载
# docker pull 192.168.9.223:5000/sshd:v3
v3: Pulling from sshd
Digest: sha256:46d7064f74b2fd47be7014f02e81d9e96bdafb1a07bc31dccc5d912e8f26c400
Status: Downloaded newer image for 192.168.9.223:5000/sshd:v3
[root@dockers ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.9.223:5000/sshd v3 fdfec675a68c 5 days ago 218MB
[root@dockers ~]# docker tag 192.168.9.223:5000/sshd:v3 sshd:v4
[root@dockers ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
192.168.9.223:5000/sshd v3 fdfec675a68c 5 days ago 218MB
sshd v4 fdfec675a68c 5 days ago 218MB
最后删除上面192.168*的镜像就行
TLS + SSL 等compose的时候再弄
18、安全防护与配置
在评估Docker的安全性时,主要考虑下面几个方面:
- linux内核的命名空间机制提供的容器隔离安全;
- Linux控制组机制对容器资源的控制能力安全;
- linux内核的能力机制所带来的操作权限安全;
- Docker程序本身的搞***性;
- 其它安全增强机制( apparmor, SELinux等) 对容器安全性的影响;
- 通过第三方工具(如Docker Bench工具)对Docker环境的安全性进行评估
19、高级网络功能
19.1、通过参数指定网络
其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效。
-b BRIDGE 或 --bridge=BRIDGE 指定容器挂载的网桥
--bip=CIDR 定制 docker0 的掩码
-H SOCKET... 或 --host=SOCKET... Docker 服务端接收命令的通道
--icc=true|false 是否支持容器之间进行通信
--ip-forward=true|false 请看下文容器之间的通信
--iptables=true|false 是否允许 Docker 添加 iptables 规则
--mtu=BYTES 容器网络中的 MTU
下面2个命令选项既可以在启动服务时指定,也可以在启动容器时指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 docker run 时可以覆盖设置的默认值。
--dns=IP_ADDRESS... 使用指定的DNS服务器
--dns-search=DOMAIN... 指定DNS搜索域
最后这些选项只有在 docker run 执行时使用,因为它是针对容器的特性内容。
-h HOSTNAME 或 --hostname=HOSTNAME 配置容器主机名
--link=CONTAINER_NAME:ALIAS 添加到另一个容器的连接
--net=bridge|none|container:NAME_or_ID|host 配置容器的桥接模式
-p SPEC 或 --publish=SPEC 映射容器端口到宿主主机
-P or --publish-all=true|false 映射容器所有端口到宿主主机
19.2、容器访问外部网络
容器默认是可以访问到宿主机本地的,但如果容器想通过宿主机访问到外部网络,需要宿主机进行转发。
在宿主机Linux系统上,检查转发是否开启;
为1时表示开启,为0表示没有开启
[root@dockers ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
[root@dockers ~]# syscl -w net.ipv4.ip_forward=1
更简单的可以在运行容器时直接 --ip-forword=true。docker服务就会自动打开宿主机的转发服务
19.3、容器之间的访问
容器之间的访问需要两方面的支持
1、网络拓扑是否连接,默认情况下容器都会连接到docker0网桥上,这意味着默认情况下拓扑是互通的。
2、本地系统的防火墙iptables是否允许通过,这取决于防火墙的默认规则是允许还是禁止。
一. 访问所有端口
当启动docker服务的时候,默认会添加一条"允许"策略到iptables的FORWARD链上,通过配置 --icc=true|false (默认为true)允许可以控制默认的策略,
同时如果启动docker服务时手动指定 --iptables=false 参数则不会修改宿主机上的iptables规则
二. 访问指定端口
通过icc=false禁止容器相互访问后,仍可通过 --link=CONTAINER_NAME:ALIAS选项来允许访问指定容器的开放端口。
也可以同时使用icc=false,iptables=true参数来配置容器间禁止访问,并允许docker自动修改系统中的iptables规则.
其实也可以直接使用--link=container:alias就直接互相连接了。
19.4、自定义网桥
先创建一个docker0的网桥,使用veth pair创建一对虚拟网卡,一端放到新创建的容器中,并重命名eth0,另一端放到宿主机上,以veth+随机7个字符串命名,并将这个网络设备加入到docker0网桥中,网桥自动为容器分配一个IP,并设置docker0的IP为容器默认网关。
1、停止容器 关掉默认网桥
Host# systemctl stop docker
Host# ip link set dev docker0 down
Host# brctl delbr docker0
2、新建网桥
Host# brctl addbr bridge0
Host# ip addr add 172.15.1.1/24 dev bridge0
Host# ip link set dev bridge0 up
# 如果本地网卡,这样获取的就是局域网地址 比如ens160,注意如果是这样的话一定要使用脚本的方式,否则连接会断开,这里bridge0 地址也应该是ens160的地址
Host# ip addr add 172.15.1.1/24 dev bridge0
Host# ip link delete dev ens160
Host# brctl addif bridge0 ens160
Host# ip link set dev bridge0 up
查看网桥
Host# ip addr show bridge0
658: bridge0: mtu 1500 qdisc noqueue state UNKNOWN
link/ether b2:03:32:49:8d:98 brd ff:ff:ff:ff:ff:ff
inet 172.15.1.1/24 scope global bridge0
valid_lft forever preferred_lft forever
inet6 fe80::b003:32ff:fe49:8d98/64 scope link
valid_lft forever preferred_lft forever
3、启动时使用bridge0网桥
Host# cat /etc/docker/daemon.json
{
"insecure-registries":["192.168.9.223:5000"],
# 添加这行,如果还有多行直接 , 换下一条添加
"bridge": "bridge0",
"registry-mirrors": [
"https://registry.docker-cn.com"
]
}
以上配置,方式一 与方式二都需要
# 方式一: 运行一个自动获取地址的容器
[root@dockers ~]# docker run -dit centos
81e9afed70b68a74d4c1e28919a3e0f3df8afdc5d06c74b74fc54ec9b879180f
# 查看网络连接
[root@dockers ~]# docker inspect reverent_kapitsa
"Networks": {
"bridge": {
"Gateway": "172.15.1.1",
"IPAddress": "172.15.1.2",
"IPPrefixLen": 24,
方式二: 手动建立虚拟机与宿主机的网络连接
# 获取容器的PID
Host# C_PID=$(docker inspect -f '{{.State.Pid}}' 12ba)
Host# echo $C_PID
26467
# 创建虚拟网卡连接目录
Host# mkdir -p /var/run/netns/
Host# ln -sv /proc/$C_PID/ns/net /var/run/netns/$C_PID
"/var/run/netns/26467" -> "/proc/26467/ns/net"
# 这里创建的是双向连接 本地的叫veth$C_PID 容器名 vp$C_PID
Host# ip link add veth$C_PID type veth peer name vp$C_PID
# 添加虚拟网卡到 bridge0中
Host# brctl addif bridge0 veth$C_PID
Host# brctl show
bridge name bridge id STP enabled interfaces
br-105ebee92a2d 8000.0242793f667e no
bridge0 8000.22902f9a823c no veth26467
vethf240758
# 启动这个网卡
Host# ip link set veth$C_PID up
# 给进程配置一个network namespace
Host# ip link set vp$C_PID netns $C_PID
# 在容器进程中设置网卡信息
# 将vp$C_PID重名命为eth0
Host# ip netns exec $C_PID ip link set dev vp$C_PID name eth0
Host# ip netns exec $C_PID ip link set eth0 up
Host# ip netns exec $C_PID ip addr add 172.15.1.2/25 dev eth0
Host# ip netns exec $C_PID ip route add default via 172.15.1.1
# 进入容器查看IP地址
[root@12ba56d1dc2b /]# ip addr show
626: eth0@if627: mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 82:b2:38:d2:2f:11 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.15.1.2/25 scope global eth0
# 在容器外查看详细信息还是会为空
[root@dockers ~]# docker inspect 12ba
"Networks": {
"none": {
"Gateway": "",
"IPAddress": "",
简单运行的脚本
#!/bin/bash
#
container_name=$(docker run -dit centos)
# 获取容器的PID
C_PID=$(docker inspect -f '{{.State.Pid}}' $container_name)
# 创建虚拟网卡连接目录
dir=/var/run/netns/
if [ ! -d $dir ];then
mkdir -p /var/run/netns/
fi
ln -sv /proc/$C_PID/ns/net /var/run/netns/$C_PID
# 这里创建的是双向连接 本地的叫veth$C_PID 容器名 vp$C_PID
ip link add veth$C_PID type veth peer name vp$C_PID
# 添加虚拟网卡到 bridge0中
brctl addif bridge0 veth$C_PID
# 启动这个网卡
ip link set veth$C_PID up
# 给进程配置一个network namespace
ip link set vp$C_PID netns $C_PID
# 在容器进程中设置网卡信息
ip netns exec $C_PID ip link set dev vp$C_PID name eth0
ip netns exec $C_PID ip link set eth0 up
ip netns exec $C_PID ip addr add 172.15.1.3/24 dev eth0
ip netns exec $C_PID ip route add default via 172.15.1.1
19.5、pipework
使用pipework配置
设置 网桥信息
Host# brctl addbr bridge0
Host# ip addr add 172.15.1.1/24 dev bridge0
Host# ip link set dev bridge0 up
# 如果本地网卡,这样获取的就是局域网地址 比如ens160
Host# ip addr add 172.15.1.1/24 dev bridge0
Host# ip link delete dev ens160
Host# brctl adif bridge0 ens160
pipework下载地址:https://github.com/jpetazzo/pipework
Host# git clone https://github.com/jpetazzo/pipework.git
创建两个容器
Host# docker run -dit --name test1 --net=none centos
Host# docker run -dit --name test2 --net=none centos
Host# ./pipework bridge0 test1 172.15.1.10/[email protected]
Host# ./pipework bridge0 test2 172.15.1.11/[email protected]
前面172.15.1.10/24是要给容器设置的地址,后面172.15.1.1 是网关地址
测试
Host# docker exec -it test1 /bin/bash
[root@f61de5354791 /]# ping 172.15.1.11
PING 172.15.1.11 (172.15.1.11) 56(84) bytes of data.
64 bytes from 172.15.1.11: icmp_seq=1 ttl=64 time=0.090 ms
20、libnetwork
三种基本元素需要了解:
1、Sandbox(沙盒):代表一个容器 ( 准确的说,是其网络命名空间);
2、Endpoint(接入点):代码网络上可以挂载容器的接口,会分配IP地址;
3、Network可以连接多个接入点的一个子网;
cnm容器管理系统,流程:驱动自动注册到网络控制器,网络控制器使用驱动类型来创建网络,然后在创建的网络上创建接口,最后把容器连接到接口上即可。销毁先把容器从接入口上卸载,然后删除接入口和网络。
目前cnm支持的驱动类型有四种:null、bridge、overlay、remote
null:不提供网络服务,容器启动后无网络连接;
bridge:docker传统上默认用linux网络和iptables实现的单机网络;
Overlay:vxlan隧道实现的跨主机容器网络
remote:扩展类型,预留给其它外部实现的方案,比如sdn方案 如(openstack neutron)
网络和和容器有如下约定:
同一个网络中的容器可以相互通信
分流容器网络流量主要利用多网络的放肆实现,所以所有的Driver都要支持多网络
一个容器可以通过多Endpoint的方式,而属于多个网络
一个Endpoint加入了一个SandBox之后,才能获得网络连通性
Docker 将会支持network相关的命令,这些命令用由libnetwork来实现,命令用法如下
docker network
Usage: docker network [OPTIONS] COMMAND [OPTIONS] [arg...]
Commands:
create 创建
rm 删除
ls 列出所有
info 显示描述信息
Run 'docker network COMMAND --help' for more information on a command.
--help=false 打印使用
[root@dockers ~]#
[root@dockers ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a36bdd783f62 bridge bridge local
43b935933822 host host local
4ee7cee4fc1c none null local
分别为三种驱动的网络: bridge,host,none
20.1、创建网络
命令格式: docker network create [options] NETWORKNAME
支持参数包括:
--aux-address value:辅助的IP地址;
-d, --deiver string:网络驱动模型,如bridge或overlay;
--gateway value: 网络地址
--ip-range value:分配IP地址范围
--ipv6:支持IPV6地址
--label value:为网络添加元标签信息
20.2、删除网络
删除指定的网络,当网络上并不存在接入点Endpoint时,删除成功。
格式: docker network rm networkname
20.3、接入容器
格式:docker network connect [options] network container
支持参数包括:
--alias value:为容器添加一个别名,此别名仅在所添加网络上可见
--ip string:指定IP地址
--ip6 string:指定ipv6地址
--link value:添加链接到另一个容器,类似vlan互通
--link-local-ip value:为容器添加一个链接地址
20.4、卸载查看容器
将一个连接到网络上的容器从网络上移除
格式: docker network disconnect [OPTIONS] network container
支持参数 -f --force强制把容器从网络上移除
查看已存在网络的具体信息
格式:docker network inspect [OPTIONS] NETWORK
支持参数 -f --format string:给定一个golang模板字符串,对输出结果进行格式化
20.5、构建跨主机的容器网络
使用libnetwork中的overlay类型驱动来实现跨主机的容器网络通信。overlay驱动默认使用vxlan协议,在IP地址可以互相访问多个主机上之间搭建隧道,让容器可以互相访问。
在libnetwork网络方案中,要实现跨主机容器网络也需要类似的一个网络信息管理机制,这个机制简单得多,只是一个键值数据库而已,如Consul,etcd,Zookeeper等工具都可以满足需求,如图
以consul为例,启动一个progrium/consul容器,并映射服务到本地的8500端口,用如下命令
docker run -d -p 8500:8500 -h consul1 progrium/consul -server -bootstrap
所在主机作为数据库节点
再启动两台docker主机 n1 和n2 确定两台机器能互相通信