本篇将介绍Docker容器通信和数据存储方面的知识。
这是Docker默认的网络模式, 在该模式中,Docker守护进程创建了一个虚拟以太网桥docker0,使宿主机上任何网卡之间能自动转发数据包。默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0接口,另一个接口放置在宿主机的命名空间,从而将宿主机上的所有容器都连接到这个内部网络。同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器。
原理:通过单机以太网桥docker0通信
该模式中将禁用Docker容器的网络隔离,容器共享宿主机的网络命名空间,直接暴露在公网中,容器会继承宿主机的IP地址。使用host模式会将容器直接暴露在公网,会存在安全隐患 。
原理:共享宿主机的网络命名空间,容器会继承宿主机的IP地址
容器会使用另一个容器的网络命名空间。使用方式为:–net=container:containername
原理:共享指定容器网络空间
该模式将容器放置在自己的网络栈中,并不进行任何配置,该模式实际上是关闭了容器的网络功能
原理:该模式未配置网络,实际上是关闭了网络功能
在docker run的时候可以通过 –net=xxx 或者 –network=xxx 来指定使用哪一种网络模式启动容器
Docker启动的时候会在主机上自动创建一个docker0网桥,实际上是一个Linux网桥,所有容器的启动如果在docker run的时候没有指定网络模式的情况下都会挂载到docker0网桥上。这样容器就可以和主机甚至是其他容器之间通讯了。
brctl show
查看Docker0的IP地址:
ifconfig
–bip=CIDR IP地址加掩码,如:192.168.1.5/24
–mtu=BYTES 覆盖默认的mtu(接口允许接收最大传输单元)配置
通过三个系统配置文件来维护,/etc/resolv.conf、/etc/hostname、/etc/hosts,
其中:
/etc/resolv/conf: 在创建容器的时候,会默认与本地主机/etc/resolv.conf保持一致
/etc/hosts: 中则记载了容器自身的一些地址和名称。
/etc/hostname: 中记录的容器的主机名
可以直接在容器内部修改这三个文件使之直接生效,但是,这些修改只会在容器中保留,容器重启后则又会恢复原样,同样的,docker commit也无法保存这三个文件的修改。
通过启动参数指定主机名
可以通过docker run的时候使用 -h hostname 或者 –hostname hostname 这样的形式来执行
全局指定DNS
可以统一配置所有容器的DNS,通过修改主机 /etc/docker/daemon.json 增加以下内容
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
通过启动参数指定DNS
通过在docker run的时候使用 –dns=address 参数来指定.
默认情况下,容器可以访问到外部网络的连接,因为容器的默认网络接口为docker0网桥上的接口,也即是主机上的本地接口。其原理是通过Linux系统的转发功能实现的,在Linux中检查转发是否打开:
[root@VM_0_14_centos ~]# sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
0表示转发未打开,1表示转发已经打开。可以在docker run时使用–ip-forward=true来指定,Docker会打开主机的转发功能。
同时可以通过上述的 nat表 中找到对应的规则,这个规则就是把所有原地址在172.17.0.0/16网段但不是属于Docker0的网包(即容器中的网包),动态伪装为0.0.0.0/0网段,即主机网卡
端口映射
使用docker run的时候使用-P或者-p来进行容器和主机之间的端口映射。
使用-P则不需要指定任何映射关系,默认情况下,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口。
原理分析:
不管使用哪一种方式进行端口映射,其他原理都是在本地的iptable的nat表中添加相应的规则,将访问外部IP地址的网包进行目标地址的转换,将目标地址修改为容器的IP地址。可以通过以下命令来查看iptable的nat表
从上面可以看到,Docker中跑了一个容器名为redis,并且把本机的62255端口映射到了容器的6379端口上。
通过查看nat表,可以看到,有两条链。POSTRONTING的第二个规则负责包到达网络接口时,改写其目的地址,将所有的流量都扔到DOCKER链,而DOCKER链的第二个规则将所有不是从docker0进入的网包,将目标端口为62255的,都修改目标地址为172.17.0.2,端口为6379。
通过docker run中的 –link=container_name:alias 参数
此种方式可以很方便让容器使用容器名进行通讯,而不需要依赖ip地址,不过link方式仅仅解决了单机容器间的互联,多机的情况下,需要通过别的方式进行连接。
原理分析
--link test1 test1是一个已存在并运行着的容器,--link的作用就相当于在当前容器的/etc/hosts中添加了一条容器名与ip的映射关系。以后当前容器就可以直接使用容器名与test1进行通信了。
除了使用link方式,还可以使用自定义网桥的方式进行互联
上面演示了创建一个bridge类型网络my-net
然后创建了两个容器centos1、centos2都连接到这个容器,然后进入centos1,使用ping centos2成功
Tips:该方式基本已经弃用,实际生产中一般都是通过k8s等容器编排服务进行容器的集群管理
在主节点上执行 docker swarm init
进行集群初始化:
添加工作节点
通过初始化集群时生成的token:
docker swarm join --token SWMTKN-1-1ltfi1qlxklu5qp5ji4m29el2sw59k4owmr9tidm7f0thjtzvk-9utkkupbktvesdebocre8yol8 主节点ip:2377
添加管理节点(记录,未验证)
docker swarm join-token manager
docker network create -d overlay --attachable net
此时,在其它节点执行 docker network ls, 可以看到该网络已同步到所有节点,不同节点的主机指定该网络创建的容器之间网络互通
通过docker network ls
可以创建一个网络,可以通过 -d 参数指定网络模式,同时 –subnet 指定子网的ip以及掩码。最后是网络名称
示例: docker network create -d bridge --subnet 172.25.0.0/16 mynet
命令: docker network connect)
示例:docker network connect mynet containername
命令:docker network ls
可以看到默认情况下docker会存在3个网络分别使用对应的网络模型名称作为网络名称。在启动容器的时候可以使用–net或–network来指定使用哪个网络,默认情况下使用bridge网络,它是一个bridge类型的网络。
命令:docker network rm
命令:docker networdk disconnect
命令:docker network inspect 网络名
Docker存储驱动(storage driver)是Docker的核心组件,它是Docker实现分层镜像的基础
性能和稳定性存在问题,不推荐在生产中使用。
btrfs,社区实现btrfs drivcer,稳定性和性能存在问题
overlayfs,内核3.18 overlayfs进入主线,性能和稳定性优异,第一选择
类似于Linux中mount的文件系统:
用法也类似,在运行 docker run 命令时,通过设置 -v或者–volume甚至–mount选项将宿主机的卷挂载到容器中
docker容器中的数据存放在宿主机的 /var/lib/docker/volumes 目录,前提是容器在生成的过程中明确了volumes
默认我们使用 docker rm -f
命令删除容器的时候,管理卷是不会自动删除的
若删除容器的时候要删除管理卷,在rm的时候加上 -v 参数即可(docker rm -f -v 容器名/id
)
当然你还可以直接去/var/lib/docker/volumes下删除,但是不推荐这么做,因为如果你直接去目录里面删除,你再用这个命令查看的话里面还有有很多记录,所以日常建议搭建用-v参数或者直接来管理卷这里删除
docker volume create [卷名称]
注意:该方式需要运行容器时进行绑定卷
`docker run --name 容器名称 -v [卷名称]:[映射容器路径] -d 镜像名称`
TIP:该方式创建的数据卷在删除容器的时候加上-v参数管理卷是不会删除的,而第一种方法会删除
若镜像没有做过管理卷,又不想使用dockerfile再生成一遍,就可以使用绑定卷
1. 首先我们在宿主机上创建了一个/data目录,并特意制作了一个镜像centos6.5v1.0这个镜像
2. 使用-v参数将宿主机上的/data和容器中的/data进行绑定
3. 最后我们在宿主机上的/data下创建了10个文件,然后去容器中查看也有,说明测试成功
1. 绑定卷可以将宿主机上的任意目录绑定到容器中,只要在run的时候使用-v参数即可,使用很方便。
2. 容器删除以后目录不会消失。
3. 绑定卷使用docker volume ls是查看不到的。
数据卷目录(指定文件夹与容器进行关联)
docker run -itd --name 容器名字 -v 宿主机目录:容器目录 镜像名称 [命令(可选)]
注意:这里的宿主机目录必须是绝对路径!!
示例:
docker run -dit --name test -v /home/python/china:/china ubuntu
数据卷文件(数据卷文件与容器文件进行关联)
docker run -itd --name 容器名字 -v 宿主机文件:容器文件 镜像名称 [命令(可选)]
注意:容器里面的文件虽然可以改名,但类型必须和宿主机文件一致
示例:
docker run -dit --name test2 -v /home/python/a.txt:/china2.txt ubuntu
查看数据卷的挂载映射情况
宿主机上可以通过docker inspect 命令来查看数据卷的挂载映射情况。
docker inspect -f {{.Mounts}} 682ccdc258b6
指定挂载模式
Docker默认会以读写模式挂载数据卷,如果想以只读方式挂载数据卷,可以在名称后通过冒号设置相应的权限。
比如读取宿主机上的配置文件,可以使用 -v /var/lib/volume4registry:/mnt :ro
数据卷容器是一个特殊的容器,专门用来提供数据卷供其它容器挂载的容器,适用于容器间共享数据,这样就可以让Docker去负责管理卷,这样做遵循了单一职责这一原则。
容器间可以共享数据卷容器,不过数据是保存在数据卷内,并没有保存到宿主机的文件目录中
docker create -v 容器数据卷目录 --name 容器名字 镜像名称 [命令(可选)]
补充:
使用docker run -v
选项指定宿主机中的卷,以及该卷在容器中要挂载的路径。若省略了宿主机中的路径,那么你就创建了一个数据卷容器
当退出这个容器之后,可以通过 docker inspect
命令来查看这个数据卷被保存到了宿主机的什么位置。 Docker 会在 /var/lib/docker/volumes/ 下为这个卷创建对应的文件夹。
docker run --volumes-from 数据卷容器id/name -tid --name 容器名字 镜像名称 [命令(可选)]
示例:
创建vc-ubuntu-test1容器
docker run --volumes-from vc-ubuntu -dit --name vc-ubuntu-test1 ubuntu
创建vc-ubuntu-test2容器
docker run --volumes-from vc-ubuntu -dit --name vc-ubuntu-test2 ubuntu
使用方法是在run的时候,加上 -v 参数指定宿主机上的目录和容器上的目录进行绑定即可,我们可以利用这个方式进行容器间的数据共享。绑定卷中宿主机上的目录可以同时跟多个容器进行绑定,这样就实现的容器间的数据共享
特点:使用绑定卷的方式进行容器间的数据共享的话,需要借助宿主机的一个目录进行共享。
原理是共享容器的管理卷,这就意味着需要有一个声明了管理卷的容器,当然也可以手动创建管理卷,具体的操作是通过参数 –volumes-from 指定共享的卷
特点:原理上就是共享数据卷
和联合卷类似,不过的是通过参数 –volumes-from 指定共享的数据卷容器
至此,我们应该对Docker的工作原理有一定的了解,这是实战运用的基础,博主一直认为学习必须是 “知其然,知其所以然”,最后附上思维导图附件, ╮(╯▽╰)╭ 非白嫖资源!
思维导图:Docker 学习笔记-基础篇003.pdf