本文全面介绍 Docker 的高级玩法,包括容器镜像和容器的概念及关系,容器与虚拟机的区别,Docker 引擎和架构,镜像分层特点及相关技术,制作 Docker Image 的两种方式,数据存储的三种挂载方式(Volumes、bind mounts、tmpfs)及特点。
一、容器镜像和容器
镜像是一个可执行包,包含运行应用程序所需的所有内容——代码、运行时、库、环境变量和配置文件。容器是通过运行镜像启动容器,是镜像的运行时实例。镜像实际上就是一个容器的模板,通过这个模板可以创建很多相同的容器。
通过Java去类比理解Docker的一些概念:
Class文件 - 相当于Docker镜像,定义了类的一些所需要的信息 对象 - 相当于容器,通过Class文件创建出来的实例 JVM - 相当于Docker引擎,可以让Docker容器屏蔽底层复杂逻辑,实现跨平台操作
二、容器与虚拟机的区别
容器在Linux上本地运行,并与其他容器共享主机的内核。它运行一个独立的进程,不占用比其他任何可执行程序更多的内存,使其轻量级。
虚拟机(VM) 运行一个成熟的“游客”操作系统,通过虚拟机监控程序对主机资源进行虚拟访问。通常,vm提供的资源比大多数应用程序所需的要多。
总的来说,容器不需要依赖操作系统,减少了很多系统资源开销,使得容器可以更关注应用的需求,而虚拟机可以为每个应用灵活提供不同的操作系统,避免了docker容器直接依赖主体机器操作系统,两者结合使用,可以让整个系统架构更加灵活,扩展性更强。
三、Docker引擎和架构
Docker引擎是一个客户端-服务器应用程序,主要组件如下:
服务器是一种长时间运行的程序,称为守护进程(dockerd)命令)。 一个REST API,它指定了程序可以用来与守护进程对话的接口指导它做什么。 命令行接口(CLI)客户端(docker命令)。
我们使用的docker指令都是通过docker客户端去与docker服务端进行通讯。
Docker架构体系
Docker使用客户机-服务器架构。 Docker客户机与Docker守护进程进行对话,后者负责构建、运行和分发Docker容器。 Docker客户机和守护进程可以在同一系统上运行,也可以将Docker客户机连接到远程Docker守护进程。Docker客户机和守护进程通过UNIX套接字或网络接口使用RESTAPI进行通信。
Docker的镜像分层
Docker镜像是由一系列层构成的。每一层代表镜像Dockerfile中的一条指令。除了最后一层之外,每一层都是只读的。Docker镜像分层最大的好处是共享资源,其他相同环境的软件镜像都共同去享用同一个环境镜像,而不需要每个软件镜像要去创建一个底层环境。
以Tomcat镜像为例子,对于用户而言,用户面向的是一个叠加后的文件系统,我们对Tomcat容器做任何操作都会记录在容器层,底层镜像文件不会受影响。Docker容器底层共享主机内核,只保留少量运行Image必须的组件,在容器启动时不需要启动内核空间,所以启动时比虚机较快,开销少,易迁移。
Docker Image是有多层结构,实际上由一层一层的文件系统组成,底层都是共享宿主Linux内核,Image的分层结构是是为了提高复用性。Image可以看作是Java的class文件,容器可以看成是JAVA的对象去理解,下层的每一层镜像可以看作是JAVA中的父类,上层镜像可以共享底层镜像的组件,类似JAVA中的继承规则。
Docker Image 基于 Union file systems做镜像和容器分层,避免在每次以新容器运行图像时复制一组完整的文件。将更改分隔为其自身层中的容器文件系统,允许将同一容器置于从已知内容重新启动(因为在删除容器时,更改的图层将被关闭)。
面向用户的是Container层,所有用户新增环境依赖和数据都会保存在容器层,下层Image只可读、不可修改。
Container是一种轻量级的虚拟技术,不需要模拟硬件创建虚拟机启动内核空间,因此启动速度很快。
Docker是基于Linux Kernel的Namespace、CGroups、UnionFileSystem等技术封装成的一种自定义容器格式,从而提供一套虚拟运行环境。
Namespace:对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响,比如pid[进程]
、net[网络]
、mnt[挂载点]
等。
CGroups: cgroup和namespace类似,也是将进程进行分组,但它的目的和namespace不一样,namespace是为了隔离进程组之间的资源,而cgroup是为了对一组进程进行统一的资源监控和限制,比如内存、CPU、进程数等。
Union file systems:用来做image和container分层。
四、制作Docker Image的两种方式
通过Dockerfile制作(推荐) - Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。 通过Docker commit操作 - 通过docker commit命令反向基于容器副本创建一个新的镜像文件。但是使用docker commit看不到Image的创建过程,因此对排查问题不友好。
五、Docker数据存储方式
Docker容器对于宿主机器来说只是一个运行在Linux上的应用,因此它的数据存储还是会依赖宿主机器,Docker是通过挂载宿主机文件系统或内存的方式来实现数据存储的,挂载方式有三种:volume、bind mount和tmpfs。
volumes - 在宿主的文件系统上的docker工作路径下创建一个文件夹(/var/lib/docker/volumes)来存储数据,其他非docker进程是不能修改该路径下的文件,完全由docker来管理。
bind mounts - 可以存储在宿主机器任何一个地方,但是会依赖宿主机器的目录结构,不能通过docker CLI 去直接管理,并且非docker进程和docker进程都可以修改该路径下的文件。
tmpfs - 无论是在Docker主机上还是在容器内,tmpfs挂载都不会持久保存在磁盘上,它会将信息存储在宿主机器内存里。容器在其生存期内可以使用它来存储非持久状态或敏感信息。例如,在内部,swarm services 使用tmpfs挂载将机密挂载到服务的容器中 或者 我们一些不需要持久化数据的开发测试环境,可以使用tmpfs。
Volumes
Volumes 是Docker推荐的挂载方式,与把数据存储在容器的可写层相比,使用Volume可以避免增加容器的容量大小,还可以使存储的数据与容器的生命周期独立。
与bind mounts相比,volumes更易于备份或迁移。 可以使用Docker CLI命令或Docker API管理Volumes。 volumes在Linux和Windows容器上均可工作。 可以在多个容器之间更安全地共享volumes。 volumes驱动程序使您可以将volumes存储在远程主机或云提供程序上,以加密volumes内容或添加其他功能。
通过–mount方式
-v
能做的–mount
指令都可以做,与-v指令对比,–mount指令更灵活,支持更多复杂操作,并且不需要严格按照参数顺序,通过key value键值对方式进行配置,可读性更高。
–mount
有以下几个参数:
type - type可以是bind、volume或者tmpfs,默认是volume。 source - 宿主机上的目录路径,可以用缩写src。 destination - 目标路径,容器上挂载的路径,可以用dst或者 target。 readonly - 可选项,如果设置了,那么容器挂载的路径会被设置为只读。 volume-opt - 可选项,当volume驱动接受同时多个参数作为选项时,可以以多个键值对的方式传入。
bind mounts
与volumes相比,bind mount的功能有限。使用绑定安装时,会将主机上的文件或目录安装到容器中。文件或目录由主机上的完整或相对路径引用。相比之下,当您使用volume时,将在主机上Docker的存储目录中创建一个新目录,并且Docker管理该目录的内容。
该文件或目录不需要在Docker主机上已经存在。如果尚不存在,则按需创建。bind mounts性能非常好,但是它们依赖于具有特定目录结构的主机文件系统。如果要开发新的Docker应用程序,请考虑使用命名volume。您不能使用Docker CLI命令直接管理bind mounts。
tmpfs
使用tmpfs不会持久化数据,数据只会存放在宿主机器内存中。
(版权归原作者所有,侵删)
免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系Docker中文社区!
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...