引言
这一篇文章,理论和实践各占一半,有需要的可以先安装配置好两台虚拟机和Docker。
觉得写的可以不妨点个赞吧,收藏比赞高N倍,枯了😂~
文章导读
- Docker的C/S架构
- Docker容器的网络连接
- Docker容器的数据管理
一、Docker的C/S模式
Docker的C/S架构中,最重要的就是Docker Client和Docker Daemon。
1.1 Docker的C/S模式
Docker守护进程会在Docker启动后,在宿主机后台运行,负责处理docker的各种命令功能。用户并不是直接和守护进程交互,而是和Docker客户端交互。意思是我们输入的命令,通过命令行接口(/bin/bash这样二进制的程序),再传递给守护进程,守护进程再将命令执行后返回结果给客户端,显示于命令行接口。
![](https://i-blog.csdnimg.cn/blog_migrate/22c6a58c790517a6e4101e127a4d00f1.png)
docker客户端除了以命令的方式和守护进程通信,还可通过Remote API。
![](https://i-blog.csdnimg.cn/blog_migrate/6c9330c1b9bf22a96a1fe84a785a6a74.png)
客户端与守护进程的连接方式
从整体上来看,用户通过命令行接口或应用程序(程序是对Remote API的封装)来对Docker Client进行访问,而这个客户端是以Socket的方式来对守护进程访问的。
Docker是以Socket的方式连接,有三种模式:
- unix://var/run/docker.sock(默认)
- tcp://host:port
- fd://socketfd
![](https://i-blog.csdnimg.cn/blog_migrate/ac21ff594f59b9d8f16fa492d59414a3.png)
1.2 Docker守护进程的配置和操作
使用service命令管理
- service docker start
- service docker stop
- service docker restart
Docker的启动选项
docker -d [OPTIONS]
- 运行相关
-D,--debug:是否开启debug
-e, 运行时使用的驱动模式
-g ,指定docker写入文件的地址
--icc :指定容器之间是否可以互相连接
-l,--log-level:设置日志界别
-p,pidfile默认为"/var/run/docker.pid" - 服务器连接相关
-G,指定用户组,默认是"docker"
-H,按照上一节所讲的Socket连接模式来写
--tls=false 安全性相关选项
... ... - RemoteAPI相关
--api-enable-cors 是否使用RemoteAPI - 存储相关
-s:storage driver,设置驱动
--selinux-enable:是否开启selinux
... ... - Registry相关
--registry-mirror:配置镜像连接 - 网络设置相关(下一章会讲)
-ip
-ip-forward:决定是否会转发流量
--iptables :允许容器与iptables设置的ip之间的访问
... ...
具体配置可以参考官网: 详细配置说明
除了通过设置启动时的参数,也可以通过配置docker启动时的配置文件,/etc/default/docker设置详细的配置项。
二、Docker容器的网络连接
Docker的网络连接部分主要包括:
- Docker容器的网络基础
- Docker容器的互联
- Docker容器与外部网络的连接
- Docker容器的跨主机访问
2.1 Docker容器的网络基础
Docker守护进程启动后,在宿主机中查看网卡信息,会发现多了一个网卡(Docker0)。Docker0其实就是一个Linux虚拟网桥。
提到这里,先回顾一下什么是网桥?
网桥工作于数据链路层,通过网络设备的物理地址(MAC地址)对网络进行划分,在不同网络之间传递数据。
Linux虚拟网桥的特点是可以设置IP地址,相当于拥有一个隐藏的虚拟网卡。
docker0来说,他的IP地址为172.17.0.1,属于B类IP。子网掩码为255.255.0.0。可以计算出总共可划分65534个地址。
docker0的工作过程
Docker对网络连接的管理,是在容器启动时就初始化两端。一端是容器中的网络设备,另一端在守护进程的主机中(docker0的Host端)开放veth开头的接口,用于网桥与容器网卡的网络通信。
简单感受下网桥是怎么工作的:
- 首先安装网桥管理程序
yum install bridge-utils
- 查看网桥设备
brctl show
3. 创建一个容器
- docker run -it --name container1 centos:centos7 /bin/bash
- ctrl+P;ctrl+Q(让容器后台运行)
此时可以看到,网桥有了对应的网络。
我们也可以自定义docker0的ip网段,使用ifconfig指令:ifconfig docker0 192.168.200.1 netmask 255.255.255.0
自定义虚拟网桥
- 添加虚拟网桥
brctl addbr newbridge
ifconfig newbridge 192.168.100.1 netmask 255.255.255.0
- 更改docker守护进程的启动配置
vim /etc/default/docker
添加DOCKER_OPS="-b=newbridge"
2.2 Docker容器的互联
Docker容器的互联可分为:
- 允许所有容器互联
- 拒绝容器间互联
- 允许特定容器间的连接
前提
FROM centos:centos7
RUN yum install -y ping
RUN yum install -y nginx
RUN yum install -y curl
EXPOSE 80
CMD /bin/bash
构建镜像 docker build -t image1 .
2.2.1 允许容器间的互联
容器之间默认是可以互联的,具体可由docker守护进程的启动选项:--icc=true|false指定。
- 构建容器
docker run -it --name container1 image1
- 启动服务
nginx
- 让容器后台运行后,再启动一个容器
docker run -it --name container2 image1
- 进入各自容器,互相ping一下,发现是可行的
配置容器间的动态连接
docker容器重启后,IP会发生变化,如果服务与服务之间将IP写死调用,势必会调用失败,此时就需要link参数: docker run --link=[CONTAINER]:[ALIAS] [IMAGE] [COMMAND]
给某个想要连接的容器取别名,这样在容器重启时,对应的host文件中的映射也会变化。
2.2.2 拒绝容器间的互联
首先要修改守护进程的启动选项,就要修改docker默认的配置文件。
- vim /etc/default/docker
- 在DOCKER_OPS中添加--icc=false
执行service dockers restart后,创建的所有容器都不能互联,如果需要指定容器互联就需要下一节的操作。
2.2.3 允许特定容器间的连接
- Docekr守护进程的启动选项:
--icc=false
--iptables=true - 重启一下docker,创建容器时用--link指定
service docker restart
docker run -it --name container3 --link=container1:c1 image1
- 测试是否能连通
curl c1
2.3 Docker容器与外部网络连接
ip-forward是linux系统中的变量,决定是否会转发流量。 对应了Linux的这个系统变量:sysctl net.ipv4.conf.all.forwarding
docekr守护进程配置的ip-forword默认为true。iptables是与Linux内核集成的包过滤防火墙系统,几乎所有的Linux发行版本都包括iptables的功能。
阻止特定ip对特定容器的访问
指令格式:
iptables -I DOCKER -s 源地址 -d 目标地址 -p TCP --dport 目的端口 -j 执行操作
注:执行操作包括DROP,ACCEPT等等。
可以通过iptables -L -n
来查看系统中的一些包过滤规则。
通过一个例子感受下:
阻止192.168.29.100访问容器ip为192.168.29.111的80端口iptables -l DOCKER -s 192.168.29.100 -d 192.168.29.111 -p TCP --dport 80 -j DROP
如果是允许的化,也同理,讲DROP改为ACCEPT。
2.4 Docker容器的跨主机访问
目前搜集的至少有3中方式可以实现:
- 使用网桥实现跨主机容器连接。
- 使用Open vSwitch实现跨主机容器连接。
- 使用weave实现跨主机容器连接。
这里由于配置简单,就讲解第一种,使用网桥的方式。
主要思路:
如果将连接容器的网桥桥接到docker宿主机提供的网卡上,并将网桥分配的ip地址与docker宿主机的ip地址设置到同一网段,就能够实现容器与容器之间跨主机的通信。简单来说就是在一个宿主机中,大家都用一个网桥。
![](https://i-blog.csdnimg.cn/blog_migrate/e025a3d8d50a51f1c8c4727ea0200c1f.png)
操作步骤
- 需要两台虚拟机
IP地址:Host1(192.168.29.3),Host2(192.168.29.4) - 修改两台虚拟机中网桥的连接
vim /etc/network/interfaces
配置如下:
auto bridge
#分配网桥的方式
iface bridge inet static
address 192.168.29.3
netmask 255.255.255.0
#默认网关
gateway 192.168.29.1
#将本地的物理网卡连接到新建的网桥上
bridge_ports eth0
在另一台虚拟机中也进行类似操作。
3. 修改docker默认的网络配置
IP的划分将改成192.168.29.65~192.168.29.126和192.168.29.129~192.168.29.190
Host1中:vim /etc/default/docker
DOCKER_OPTS=" -b=bridge --fixed-cidr='192.168.29.64/26' "
Host2中:DOCKER_OPTS=" -b=bridge --fixed-cidr='192.168.29.128/26' "
4. 启动一个容器,执行ping另一台宿主机的ip或者另一台宿主机中的容器,发现能够连通则配置成功。
三、Docker容器的数据管理
有时候,我们需要容器与宿主机磁盘中的数据共享,对此,Docker提供的解决方案是数据卷技术。以容器挂载数据卷的方式来实现数据的互通。
本小节主要分为:
- Docekr容器的数据卷
- Docker的数据卷容器
- Docker数据卷的备份和还原
3.1 Docker容器的数据卷
什么是数据卷?
数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问。对数据卷应该有如下的感觉:
数据卷设计的目的在于持久化,它完全独立于容器的生存周期,因此,Docker不会在容器删除时,删除其挂载的数据卷,也不会存在类似的垃圾收集机制,对容器的数据卷进行处理。
数据卷的特点
- 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中。
- 数据卷可以在容器之间共享和重用。
- 可以对数据卷里的内容直接进行修改。
- 数据卷的变化不会影响镜像的更新。
- 卷会一直存在,即使挂载数据卷的容器已经被删除。
为容器添加数据卷
docker run -v ~/container_data:/data -it centos:centos7 /bin/bash
为数据卷添加访问权限
docker run -v 宿主机目录:容器目录:ro IMAGE COMMAND -d
注:"ro"的意思是read only。
使用Dockerfile构建数据卷
VOLUME["/data"]
这里是不需要写明映射关系的,因为通过这个镜像创建的不同容器的数据卷是不一样的。具体映射关系可以通过docker inspect CONTAINER
查看。
3.2 Docker的数据卷容器
数据卷提供了容器与宿主机的共享数据,如果容器与容器之间要共享,该怎么办呢?这就需要挂载包含数据卷的容器来实现。
什么是数据卷容器?
命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器叫数据卷容器。
文字看着又绕又枯燥,一张图梳理一下:
图中可以看出:
- 数据卷容器挂载了一个本地目录。
- 其他容器通过连接这个数据卷容器实现数据的共享。
挂载数据卷容器的方法 docekr run --volumes-from [CONTAINER]
注:CONTAINER是挂载数据卷的容器。
下面通过一个例子来实现container1与container2的数据共享。
前提
image2.dockerfile如下:
FROM centos:centos7
VOLUME["/datavolume"]
CMD /bin/bash
构建镜像后的步骤
下面步骤中container1是数据卷容器,container2和container3要实现数据共享。
- 启动container1
docker run -it --name container1 image2
- 在container1中创建文件
touch /datavolume/c1
exit
- 启动container2,并挂载到container1
docker run -it --name container2 --volumes-from container1 IMAGE /bin/bash
- 在container2中创建文件
touceh /datavolume/c2
exit
- 同理启动container3
docker run -it --name container3 --volumes-from container1 IMAGE /bin/bash
exit
docker inspect --format="{{.Volumes}}" container2
docker inspect --format="{{.Volumes}}" container3
最后,我们可以惊奇地发现两个挂载了数据卷容器的容器返回结果一样。
此时将container1容器删除,会发现,container2和container3还是共享了一个数据卷容器,因此可以得出这样的结论:数据卷容器仅仅承载配置信息的传递。
3.3 Docker数据卷的备份和还原
数据备份方法
docker run --volumes-from CONTAINER -v 期望备份存放的路径(宿主机路径):映射到备份命令容器中的目录:权限(一般为wr,即读写权限) IMAGE tar cvf 压缩至某个路径下的某个文件名(宿主机路径) 数据卷在容器中的路径
文字描述比较绕,通过例子展示一下:
docker run --volumes-from container1 -v ~/backup:/backup --name container2 IMAGE tar cvf /backup/c1.tar /datavolume1
具体过程:
备份过程其实就是对数据容器挂载的数据卷中的数据的转移,相当于执行备份命令的容器既挂载了数据容器的数据卷,又挂载了备份数据存放的数据卷。
同样地,数据还原方法就是对备份的解压缩:docker run --volumes-from container1 -v ~/backup:/backup IMAGE tar xvf /backup/backup.tar /datavolume1
总结
Docker的学习暂时告一段落,在这个过程中,最终要的还是在虚拟机中多多实践。真实运行中可能会碰到许多问题,解决问题的过程中经验才能一步一步的积累~
感觉写得还可不妨点个赞哈~