Docker简介与底层原理
# 一、Docker简介
Docker (opens new window)是一个开源的容器引擎,它将应用程序和基础设施层分离,并且能将基础设施当作应用程序一样进行管理。使用 Docker可更快地打包、测试以及部署应用程序,缩短了从编写到部署运行代码的时间。
# 二、Docker的架构
# 1.1、Docker daemon( Docker守护进程)
Docker daemon是一个运行在宿主机( DOCKER-HOST)的后台进程。可通过 Docker客户端与之通信。
# 1.2、Client( Docker客户端)
Docker客户端是 Docker的用户界面,它可以接受用户命令和配置标识,并与 Docker daemon通信。图中, docker build等都是 Docker的相关命令。
# 1.3、Images( Docker镜像)
Docker镜像是一个只读模板,它包含创建 Docker容器的说明。使用Docker镜像可以运行 Docker镜像中的程序。
# 1.4、Container(容器)
容器是镜像的可运行实例。
镜像和容器的关系有点类似于面向对象中,类和对象的关系
# 1.5、Registry
Docker Registry是一个集中存储与分发镜像的服务
Docker Registry可分为公有Docker Registry和私有Docker Registry。 最常⽤的Docker Registry莫过于官⽅的Docker Hub, 这也是默认的Docker Registry。 Docker Hub上存放着⼤量优秀的镜像, 我们可使⽤Docker命令下载并使⽤。
一个 Docker Registry可包含多个 Docker仓库,每个仓库可包含多个镜像标签,每个标签对应一个 Docker镜像。这跟 Maven的仓库有点类似,如果把 Docker Registry比作 Maven仓库的话,那么 Docker仓库就可理解为某jar包的路径,而镜像标签则可理解为jar包的版本号。
# 三、Docker底层实现
# 3.1、Docker虚拟化原理
传统虚拟化和容器技术结构比较:
容器虚拟化技术是共享了宿主机内核,几乎没有性能损耗
传统虚拟化技术是重新加载一个操作系统内核,有性能损耗
Docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。避免了寻址、加载操作系统内核这些比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的。而Docker由于直接利用宿主机的操作系统,则省略了这个过程,因此新建一个docker容器只需要几秒钟。
# 3.2、联合文件系统
Docker是如何将机器的资源进行隔离的?答案是联合文件系统,常见的有AUFS、Overlay、devicemapper、BTRFS和ZFS等。
以Overlay2举例说明,Overlay2的架构图如下:
原理:overlayfs在linux主机上只有两层,一个目录在下层,用来保存镜像(docker),另外一个目录在上层,用来存储容器信息。在overlayfs中,底层的目录叫做lowerdir,顶层的目录称之为upperdir,对外提供统一的文件系统为merged。当需要修改一个文件时,使用COW(Copy-on-write)
将文件从只读的Lower复制到可写的Upper进行修改,结果也保存在Upper层。在Docker中,底下的只读层就是image,可写层就是Container
# 3.2.1、写时复制 (CoW)
CoW全称copy-on-write,这个是针对已有文件的修改场景,只有在需要写时才去复制,这样可以有效的提高磁盘的利用率。所以容器占用的空间是很少的
比如基于一个image启动多个Container,如果每个Container都去分配一个image一样的文件系统,那么将会占用大量的磁盘空间。而CoW技术可以让所有的容器共享image的文件系统,所有数据都从image中读取,只有当要对文件进行写操作时,才从image里把要写的文件复制到自己的文件系统进行修改。所以无论有多少个容器共享一个image,所做的写操作都是对从image中复制到自己的文件系统的副本上进行,并不会修改image的源文件,且多个容器操作同一个文件,会在每个容器的文件系统里生成一个副本,每个容器修改的都是自己的副本,互相隔离,互不影响
查看容器占用磁盘大小指令:
# 查看所有容器的大小
cd /var/lib/docker/containers # 进入docker容器存储目录
du -sh * # 查看所有容器的大小
du -sh <容器完整id> #查看某一个容器的大小
2
3
4
# 3.2.2、用时分配 (allocate-on-demand)
用时分配是针对原本没有这个文件的场景,只有在要新写入一个文件时才分配空间,这样可以提高存储资源的利用率。
比如启动一个容器,并不会因为这个容器分配一些磁盘空间,而是当有新文件写入时,才按需分配新空间。
# 3.3、镜像分层技术
Docker使用共享技术减少镜像存储空间。在下载镜像时,Docker Daemon会检查镜像中的镜像层与宿主机文件系统中的镜像层进行对比,如果存在则不下载,只下载不存在的镜像层,这样可以非常节约存储空间
举个例子:下载某个应用程序的镜像时,这个应用程序需要JDK8的镜像层,此时会和宿主机中的镜像层进行对比,如果存在JDK8的镜像则不下载,若不存在,则下载JDK8的镜像,下载JDK8的镜像时,也会进行对比