docker2:容器,镜像

引言

上次,我们说了docker创建容器命令的执行过程,客户端和Daemon存在通讯,客户端把命令传递给Daemon,但Daemon本身没有执行代码,全权交给Conatinerd来做,而Containerd也不是万能的,他需要一个小弟runc来帮助他跟操作系统要资源,整个过程就像打排球。

这次我准备针对走入docker,了解镜像和容器。

镜像

大家都喜欢美食吧,我就对下面的甜点毫无抵抗力,他们酥脆可口,其实呢,我们的docker也蕴藏着一个小小的甜点制造厂。

以饼干为例,饼干的制作并不是完全手工的,他们有自己的模具,通过模具出来的饼干工整,美观一致,docker镜像就是饼干模具,产出的饼干是docker容器,它们之间的关系非常紧密。要想做出饼干,就必须要有模具,因此镜像必不可少。

镜像是什么

有很多人可能疑惑,镜像到底是什么,如果把镜像说成系统,这样对吗? 答:不对。这是因为,容器的任务是运行应用或者服务,但是运行应用/服务就需要很多资源,包括操作系统,相关文件等等,容器的模具(镜像)就必须提供这些资源,就像模具要为饼干提供形状,大小等等。你是否还记得docker是不包括操作系统的,正是这个特点,让它和其他虚拟机大不相同。正如下图这样,docker镜像既然作为docker的一部分,当然也不能说成系统,那它到底是什么呢?

其实,Docker镜像是一个文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。docker镜像确实包含了一个精简的操作系统,但这个精简操作系统没有内核,它使用真正操作系统的内核,这就像借东西一样,docker向操作系统借走内核,自己并不包含内核,像个好吃懒做的胖子。

值得注意一下,这里所说的内核是指操作系统的核心。它基于硬件的第一层软件扩充,提供操作系统最基本的功能,也是操作系统工作的基础,内核负责管理系统的进程、内存、文件和网络系统,决定着系统的性能和稳定性—百度百科

镜像怎么工作

我们所说的镜像其实是许多个只读镜像层,它更像一个夹心饼干,层层堆叠,其中最重要的是第一层,因为它是所有层的基础,比如我想创建一个Linux镜像,那么第一层就是linux,但这时,思寒要求在linux上安装python,于是就有了第二层:python,以此类推。

docker非常聪明,它会把多层镜像打包,在使用者看来,这里只有一个镜像,只有当我们输入命令时,多层镜像才会显示出来。

可以使用docker image inspect命令查看多层镜像,不过,这种堆叠式设计费力不讨好,究竟有什么用呢?

$ docker image inspect ubuntu:latest
[
{
"Id": "sha256:bd3d4369ae.......fa2645f5699037d7d8c6b415a10",
"RepoTags": [
"ubuntu:latest"

<Snip>

"RootFS": {
  "Type": "layers",
  "Layers": [
   "sha256:c8a75145fc...894129005e461a43875a094b93412",
   "sha256:c6f2b330b6...7214ed6aac305dd03f70b95cdc610",
   "sha256:055757a193...3a9565d78962c7f368d5ac5984998",
   "sha256:4837348061...12695f548406ea77feb5074e195e3",
   "sha256:0cad5e07ba...4bae4cfc66b376265e16c32a0aae9"
  ]
  }
}
]

举个例子,我想创建两个linux镜像,分别是linuxA和linuxB,你认为docker会怎么做?docker会发现这两个镜像的镜像层极其相似,于是直接共享镜像层,看似是两个镜像,实际上只有一个镜像层,这是一个十足的奸商,但这样做只用了一个夹心层,真的可以节省大量的空间!

镜像怎么被管理

docker镜像可不是孤立无援,它也有自己的归属,镜像存储在仓库中,而仓库存放在镜像仓库服务中。就像下面这个码头,docker镜像是小箱子,小箱子要被存放在集装箱中,这个集装箱就是仓库,而邮轮装载着大量的集装箱,邮轮就是仓库服务。Docker 客户端的镜像仓库服务是可配置的,默认使用Docker Hub。

Docker Hub 也分为官方仓库(Official Repository)和非官方仓库(Unofficial Repository)—http://c.biancheng.net/view/3143.html

容器

前面说过,镜像与容器的关系就像是模具和饼干,一个镜像可以创造出多个容器,容器可以被创建、启动、停止、删除、暂停等。 

容器是什么

容器是进程,它有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间,可以说麻雀虽小五脏具全,容器内也可以有进程,其内的进程与世隔绝(但会借用操作系统内核),这种特性使得容器封装的应用比直接在宿主运行更加安全。前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。 按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

内容引用自:https://yeasy.gitbooks.io/docker_practice/content/basic_concept/container.html

容器怎么工作的

docker的运行,要依赖一台物理机和操作系统,操作系统将物理机资源分配给docker,docker再把这些资源分割给不同的容器。需要注意的是,容器与容器间是相互隔离。

那么它与传统的虚拟机有什么不同呢,我将上面的图改画成下面这样,不同点还是非常多的,首先,硬件之上是Hypervisor,这是一个资源管理员,它会把资源划分为多个虚拟资源,并分配给虚拟机,每一个虚拟机内部都有自己的操作系统,操作系统之上才是应用,这是一个十分累人的过程,每一个虚拟机要维护自己的操作系统,想想就觉得后怕。

总结

本文章对镜像和容器进行了总结,但没有提及docker命令使用,因为网上有大量的文章介绍docker命令,我们有了这些理论知识,可以非常快速上手命令使用。

更多

霍格沃兹测试学院官网首页:https://testing-studio.com