Docker基础(1) 原理篇

Stella981
• 阅读 786
  • Docker是什么
  • Docker的构成
  • Docker的分层和写时拷贝策略
  • Docker与主流虚拟机的区别
  • Docker镜像与容器的关系
  • 镜像的变更管理

Docker是什么

Docker是一个开源的应用容器引擎。它的理念是“Buildonce, Run anywhere, Configure once, Run anything”,这与Java提出的“Write Once, Run Anywhere”有异曲同工之妙。 Java与Docker在面对平台移植方面的问题时,采用了类似的解决方案。Java语言使用虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成可以在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

类似地,Docker使用容器引擎解决平台依赖问题,它在每台宿主机上都启动一个Docker的守护进程,守护进程屏蔽了与具体平台相关的信息,对上层应用提供统一的接口。这样,Docker化的应用,就可以在多个平台下运行,Docker会针对不同的平台,解析给对应的执行驱动、存储驱动和网络驱动去执行。 这里说的平台主要针对不同的Linux发行版,因为Docker的实现需要用到Linux的cgroups、namespaces等特性,所以目前只能运行在Linux环境下,要想在Windows和Mac上使用Docker,则要采用虚拟机的方式。

此外,Docker还有自己的生态圈,从官方镜像仓库下载的镜像,可以运行在任何装有Docker引擎的操作系统上,开发人员也可以将自己制作的镜像提交的官方仓库供别人使用。还可以搭建私有的镜像仓库。这就类似Android或iOS系统与应用商店的关系。

最后,Docker还具有版本控制功能,可以对镜像做修改后提交新的版本、可以在多个版本间快速切换。

综上,Docker是一个开源的应用容器引擎,它的应用以镜像的形式存在,Docker通过屏蔽环境的差异,可以方便地让应用在各种环境运行,而且Docker还具有对镜像的版本控制功能。

Docker的构成

Docker有自己完善的生态圈,总体来说分为Docker镜像仓库和Docker自身程序两部分。 其中Docker自身程序又分为Server和Client两部分,采用了C/S架构,用Go语言编写。 Docker的Server端又称作Docker Daemon,在宿主机上以后台守护进程的形式运行。Docker Client使用比较灵活,既可以在本机上以bin命令的形式(如Docker info、Docker start)发送指令,也可以在远端通过RESTful API的形式发送指令;Docker的Server端接收指令并把指令分解为一系列任务去执行。

当通过Docker client发送docker run指令来创建并启动容器的时候,Docker Daemon首先会检查本地是否有对应的镜像,如果没有就从官方仓库下载,然后基于下载的镜像创建并启动容器,最后把执行结果返回给Docker Client。

Docker的分层和写时拷贝策略

Docker会把软件和它依赖的环境(包括操作系统和共享库等)、依赖的配置文件打包在一起,以虚拟机镜像的形式放到官方仓库供别人下载使用。 但操作系统的体积相对软件的体积来说太大了,为了运行软件,每次都下载配套的操作系统是不现实的。为了解决这个问题,Docker引入了分层的概念。把一个应用分为任意多个层,比如操作系统是第一层,依赖的库和第三方软件是第二层,应用的软件包和配置文件是第三层。如果两个应用有相同的底层,就可以共享这些层。越是处于底部体积大的层,共享的可能也就更大。

但分层方式还会面临共享层冲突的问题,所以Docker为文件层增加了优先级属性,上层和下层有相同的文件和配置时,上层覆盖下层。比如,应用A需要修改操作系统的某个配置,应用B不需要修改。这时给以应用A增加一个优先级最高的空白层,如果需要修改下层的文件,就把这个文件拷贝到这个空白层进行修改,保证下层的文件不做任何改变,这称为写时拷贝策略。

应用A:              
====运行的应用====== 
======空白层======== 
=====配置文件======= 
=====依赖的库======= 
=====操作系统======= 


应用B:
====运行的应用======
=====配置文件=======
=====依赖的库=======
=====操作系统=======

Docker与主流虚拟机的区别

KVM、Xen、VMWare、VirtualBox等主流的虚拟机一般比较笨重,在运行的时候,虚拟机本身就要消耗大量的系统资源(CPU、内存等),而且这类虚拟机启动时间也比较长,动辄耗时数分钟。 而以OpenVZ、VServer、LXC为代表的容器类虚拟机,是一种内核虚拟化技术,与宿主机运行在相同Linux内核,不需要指令级模拟,性能消耗非常小,是非常轻量级的虚拟化容器,虚拟容器的系统资源消耗和一个普通的进程差不多。Docker就是使用LXC(后来又推出libcontainer)让虚拟机变得轻量化。

Docker镜像与容器的关系

那么镜像与容器是什么关系呢,根据前面的描述得知:镜像指的是以分层的、可以被LXC/libcontainer理解的文件存储格式。Docker的应用都是以这种格式发布到Docker仓库中,供大家使用。而容器则是指:把应用镜像从Docker仓库下载到本地机器上,以镜像为模板,在一个容器类虚拟机中把这个应用启动,这个虚拟机叫就是容器了。 从另一个角度来说,镜像和容器可以看作是一个Docker化应用的两种不同状态。镜像状态时,一个应用只有运行所需的必要文件、程序包等内容,而且应用也处于静止态;而容器状态时,应用要运行起来以对外提供服务,有可能修改文件,比如输出日志、动态更新某个配置等等,这时需要有空白层用于写时拷贝。

镜像的变更管理

利用镜像分层存储的特性,Docker还可以做到灵活的变更管理。 比如一个Docker镜像它的V1.0版本有三层,现在要对它做如下修改:修改位于第一层的文件A;删除位于第二层的文件B;添加一个新文件C。 这时就会增加一个第四层,在这一层做修改:把第一层的文件A拷贝到第四层,修改文件A的内容;在第四层,把名称为B的文件设置为不存在;在第四层,创建一个新文件C。

v1.0:                      
                      
=====第三层 50M=====  
=====第二层 500M====  
=====第一层 1G======  


v1.1:                        
===第四层 修改 1M===
=====第三层 50M=====
=====第二层 500M====
=====第一层 1G======

这样修改就完成了,在向仓库发布这个新版本时,因为前三层已经存储在仓库,只需要上传体积很小的第四层就可以了。使用这个镜像的其它机器要升级版本时,同样也只需要从仓库下载第四层。 由此可见这种分层的特性对于Docker的重要意义,利用分层特性,Docker可以做到镜像的增量变更,使得Docker镜像的下载上传变得非常轻量(除了第一次操作)。

参考资料 李金榜 尹烨 刘天斯 陈纯 著 《循序渐进学Docker》

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这