做者| 阿里巴巴高级开发工程师 傅伟golang
在介绍容器的具体概念以前,先简单回顾一下操做系统是如何管理进程的。docker
首先,当咱们登陆到操做系统以后,能够经过 ps 等操做看到各式各样的进程,这些进程包括系统自带的服务和用户的应用进程。那么,这些进程都有什么样的特色?网络
这样的三个特色会带来什么问题呢?架构
针对上述的三个问题,如何为进程提供一个独立的运行环境呢?运维
那么,应该如何定义这样的进程集合呢?工具
其实,**容器就是一个视图隔离、资源可限制、独立文件系统的进程集合。**所谓“视图隔离”就是可以看到部分进程以及具备独立的主机名等;控制资源使用率则是能够对于内存大小以及 CPU 使用个数等进行限制。容器就是一个进程集合,它将系统的其余资源隔离开来,具备本身独立的资源视图。测试
容器具备一个独立的文件系统,由于使用的是系统的资源,因此在独立的文件系统内不须要具有内核相关的代码或者工具,咱们只须要提供容器所需的二进制文件、配置文件以及依赖便可。只要容器运行时所需的文件集合都可以具有,那么这个容器就可以运行起来。ui
综上所述,咱们将这些容器运行时所须要的全部的文件集合称之为容器镜像。spa
那么,通常都是经过什么样的方式来构建镜像的呢?一般状况下,咱们会采用 Dockerfile 来构建镜像,这是由于 Dockerfile 提供了很是便利的语法糖,可以帮助咱们很好地描述构建的每一个步骤。固然,每一个构建步骤都会对已有的文件系统进行操做,这样就会带来文件系统内容的变化,咱们将这些变化称之为 changeset。当咱们把构建步骤所产生的变化依次做用到一个空文件夹上,就可以获得一个完整的镜像。 changeset 的分层以及复用特色可以带来几点优点:操作系统
以下图所示的 Dockerfile 适用于描述如何构建 golang 应用的。
如图所示:
当有了 Dockerfile 以后,就能够经过 docker build 命令构建出所须要的应用。构建出的结果存储在本地,通常状况下,镜像构建会在打包机或者其余的隔离环境下完成。
那么,这些镜像如何运行在生产环境或者测试环境上呢?这时候就须要一个中转站或者中心存储,咱们称之为 docker registry,也就是镜像仓库,其负责存储全部产生的镜像数据。咱们只须要经过 docker push 就可以将本地镜像推进到镜像仓库中,这样一来,就可以在生产环境上或者测试环境上将相应的数据下载下来并运行了。
运行一个容器通常状况下分为三步:
简单回顾一下,容器就是和系统其它部分隔离开来的进程集合,这里的其余部分包括进程、网络资源以及文件系统等。而镜像就是容器所须要的全部文件集合,其具有一次构建、处处运行的特色。
容器是一组具备隔离特性的进程集合,在使用 docker run 的时候会选择一个镜像来提供独立的文件系统并指定相应的运行程序。这里指定的运行程序称之为 initial 进程,这个 initial 进程启动的时候,容器也会随之启动,当 initial 进程退出的时候,容器也会随之退出。
所以,能够认为容器的生命周期和 initial 进程的生命周期是一致的。固然,由于容器内不仅有这样的一个 initial 进程,initial 进程自己也能够产生其余的子进程或者经过 docker exec 产生出来的运维操做,也属于 initial 进程管理的范围内。当 initial 进程退出的时候,全部的子进程也会随之退出,这样也是为了防止资源的泄漏。 可是这样的作法也会存在一些问题,首先应用里面的程序每每是有状态的,其可能会产生一些重要的数据,当一个容器退出被删除以后,数据也就会丢失了,这对于应用方而言是不能接受的,因此须要将容器所产生出来的重要数据持久化下来。容器可以直接将数据持久化到指定的目录上,这个目录就称之为数据卷。
数据卷有一些特色,其中很是明显的就是数据卷的生命周期是独立于容器的生命周期的,也就是说容器的建立、运行、中止、删除等操做都和数据卷没有任何关系,由于它是一个特殊的目录,是用于帮助容器进行持久化的。简单而言,咱们会将数据卷挂载到容器内,这样一来容器就可以将数据写入到相应的目录里面了,并且容器的退出并不会致使数据的丢失。
一般状况下,数据卷管理主要有两种方式:
moby 是目前最流行的容器管理引擎,moby daemon 会对上提供有关于容器、镜像、网络以及 Volume的管理。moby daemon 所依赖的最重要的组件就是 containerd,containerd 是一个容器运行时管理引擎,其独立于 moby daemon ,能够对上提供容器、镜像的相关管理。
containerd 底层有 containerd shim 模块,其相似于一个守护进程,这样设计的缘由有几点:
本节课程只是针对于 moby 进行一个大体的介绍,在后续的课程也会详细介绍。
VM 利用 Hypervisor 虚拟化技术来模拟 CPU、内存等硬件资源,这样就能够在宿主机上创建一个 Guest OS,这是常说的安装一个虚拟机。
每个 Guest OS 都有一个独立的内核,好比 Ubuntu、CentOS 甚至是 Windows 等,在这样的 Guest OS 之下,每一个应用都是相互独立的,VM 能够提供一个更好的隔离效果。但这样的隔离效果须要付出必定的代价,由于须要把一部分的计算资源交给虚拟化,这样就很难充分利用现有的计算资源,而且每一个 Guest OS 都须要占用大量的磁盘空间,好比 Windows 操做系统的安装须要 10~30G 的磁盘空间,Ubuntu 也须要 5~6G,同时这样的方式启动很慢。正是由于虚拟机技术的缺点,催生出了容器技术。 容器是针对于进程而言的,所以无需 Guest OS,只须要一个独立的文件系统提供其所须要文件集合便可。全部的文件隔离都是进程级别的,所以启动时间快于 VM,而且所需的磁盘空间也小于 VM。固然了,进程级别的隔离并无想象中的那么好,隔离效果相比 VM 要差不少。
整体而言,容器和 VM 相比,各有优劣,所以容器技术也在向着强隔离方向发展。