下面我们了解一下容器网络,decker支持三种网络模式
none: 参数是 --network none 这样的话容器内部只有一个环回接口
host: 使用主机网络 参数是 --network host
container:和其他容器公用一个网络空间, 参数 --network <contain id>
bridge: 使用 Linux 网桥和 iptables 提供容器互联,Docker 在每台主机上创建一个名叫 docker0
的网桥,通过 veth pair 来连接该主机的每一个 EndPoint
bridge的网络模式可以用下面的图片来理解
下面我们通过一个小实验看看docker 是如何给容器配置ip并且给主机联通的
创建网络命名空间
mkdir -p /var/run/netns
find -L /var/run/netns -type l -delete
开启一个nginx容器设置它的网络模式为none
docker run --network=none -d nginx
查看容器Pid
docker ps|grep nginx
docker inspect <containerid>|grep -i pid
"Pid": 876884,
"PidMode": "",
"PidsLimit": null,
查看容器网络配置
nsenter -t 876884 -n ip a
链接网络namespace
export pid=876884
ln -s /proc/$pid/ns/net /var/run/netns/$pid
ip netns list
创建veth
ip link add A type veth peer name B
配置A口
brctl addif docker0 A
ip link set A up
配置B口
SETIP=172.17.0.10
SETMASK=16
GATEWAY=172.17.0.1
ip link set B netns $pid
ip netns exec $pid ip link set dev B name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
ip netns exec $pid ip route add default via $GATEWAY
现在我们ping一下配置的ip
发现可访问到nginx服务
docker 的volume管理,docker 可以通过下面两个命令把宿主机上的目录挂载到容器中
挂载操作
docker run -itd -v /test --name nginx_volume
查看挂载信息
docker volume ls
根据这个信息我们可以在宿主机上的/var/lib/docker/volumes/<volumu id>目录下看到这个目录
docker run -itd -v /home:/test --name nginx_volume2
这种方式会把宿主机上的/home 挂载到容器内的/test目录下
这种方式就是linux的bind mount,他的工作原理是inode的替换过程,而且挂载的内容也不会被docker commit掉,这是因为commit时发声在宿主机空间的,在我们使用-v参数指定挂载的时候,宿主机就会准备好这个目录,然后挂载到容器内,由于mount namespace 所以宿主机内的挂载目录里内容是空的
可以用下面的图再描述一下rootfs
这个容器进程“python app.py”,运行在由 Linux Namespace 和 Cgroups 构成的隔离环境里;而它运行所需要的各种文件,比如 python,app.py,以及整个操作系统文件,则由多个联合挂载在一起的 rootfs 层提供。这些 rootfs 层的最下层,是来自 Docker 镜像的只读层。在只读层之上,是 Docker 自己添加的 Init 层,用来存放被临时修改过的 /etc/hosts 等文件。而 rootfs 的最上层是一个可读写层,它以 Copy-on-Write 的方式存放任何对只读层的修改,容器声明的 Volume 的挂载点,也出现在这一层。任何镜像的内容都是只读层,如果你执行 docker run -v /home:/test 的时候,容器镜像里的 /test 目录下本来就有内容的话,你会发现,在宿主机的 /home 目录下,也会出现这些内容。这是怎么回事?为什么它们没有被绑定挂载隐藏起来呢,这是docker 的Copydata