Docker 概述
云计算基础概念
云计算的三种服务模式
- SaaS(Software as a Service,软件即服务):表示软件的开发、管理、部署都交给第三方,不需要关心技术问题,可以拿来即用。普通用户接触到的互联网服务,几乎都是 SaaS。
- PaaS(Platform as a Service,平台即服务):PaaS 提供软件部署平台(runtime),抽象掉了硬件和操作系统细节,可以无缝地扩展。开发者只需要关注自己的业务逻辑,不需要关注底层。
- IaaS(Infrastructure as a Service,基础设施即服务):IaaS 是云服务的最底层,主要提供一些基础资源。它与 PaaS 的区别是,用户需要自己控制底层,实现基础设施的使用逻辑。
上图中,绿色的部分是云服务商决定的,灰色的部分是用户决定的。可以看到,SaaS 模式下用户没有任何自主权,只能使用给定的应用程序;PaaS 模式下可以自己安装应用程序,但是不能定制操作系统;IaaS 模式下则是云服务商提供(虚拟的)硬件,从操作系统开始都可以自己选择和定制。
(该部分内容转载自阮一峰的IaaS,PaaS,SaaS 的区别,原文有更生动的描述。)
Docker Platform
Docker 提供了在隔离环境中打包和运行应用的能力,这里“隔离的环境”指的就是容器(container)。容器的隔离性是通过Linux Namespace技术实现的,它使得我们可以在一个宿主机上同时运行多个容器。容器是轻量级的,因为容器与容器之间共享宿主机的内核(host machine’s kernel),而不需要 Hypervisor。
关于Hypervisor,简单了解如下:
通俗来讲,Hypervisor是一种将操作系统与硬件抽象分离的方法,以达到host machine的硬件能同时运行一个至多个虚拟机作为guest machine的目的,这样能够使得这些虚拟机高效地分享主机硬件资源。
最主要的,我们需要搞清楚“容器”与“虚拟机”的区别。
容器 vs 虚拟机
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 要差很多。
Docker Engine
Docker Engine 是一个client-server 应用,主要有以下组件:
- server:一个始终在运行的后台进程(docker daemon),即
dockerd
命令(这个命令一般用不到); - REST API:应用程序通过调用REST API与docker daemon进程交互;
- command line interface(CLI) client:即
docker run...
这个命令中的docker
。
Docker architecture
Docker 使用典型的 client-server 架构,Docker client 与 Docker daemon 交互,后者负责 Docker container 的构建、运行和分发工作。Docker client 可以与 daemon 运行在同一个系统上,或者,Docker client 也可以与远程的 daemon 进行连接交互。
架构图如下:(图片来自官网)
Docker daemon
Docker daemon(dockerd
) 监听Docker client的请求,并管理Docker的对象,比如镜像(images)、容器(container)、网络(networks)和数据卷(volume)。daemon 同时也会与其他 daemon 进行通信,以此支撑起整个Docker服务。
Docker client
当你发送诸如docker run
命令时,Docker client(docker
)便会把这些命令发送给 dockerd
,由后者来真正的执行。
Docker registry
Docker registry(注册表/注册中心?) 是存放Docker images的地方,Docker Hub 是任何人都可以使用的公共注册中心。默认情况下,Docker 就是从 Docker Hub 中拉取镜像的。当然,对于国内的网络环境而言,很多时候拉取镜像会非常慢,于是就要配置成国内的镜像源,需要在 /etc/docker/daemon.json
文件(一开始并不存在这个文件,需手动创建之)中配置如下内容。这个问题新手经常遇到,比如docker pull
执行失败,往往配置成国内的镜像源就可以解决了。
{
"registry-mirrors": [
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com"
]
}
当执行docker pull
或docker run
命令时,会从配置好的registry中拉取镜像;当执行docker push
命令时,就会把你的镜像推到相应的registry上去。
Docker objects
image
镜像是用于创建Docker container的只读(read-only)模板。
我们可以自行构建镜像(通过docker build命令或docker commit命令),或者直接从registry上拉取别人的镜像(通过docker pull的方式)。这里主要说一下镜像的构建。
如果采用docker build的方式构建镜像,就需要编写Dockerfile文件,每执行一行Dockerfile指令,就会在镜像中创建一层(layer)。如果改动Dockerfile文件重新build,只会在发生变化的层重建,这也是为何容器如此轻量的原因。
而采用docker commit的方式构建镜像,是基于当前容器进行构建的。
container
container是运行着的镜像实例。
总结:可以这么理解,Docker镜像是Docker容器的静态视角,而Docker容器是Docker镜像的运行状态。
示例:分析docker run
命令的执行流程
$ docker run -i -t ubuntu /bin/bash
当执行这条命令时,会发生什么?
- 如果在本地不存在
ubuntu
这个镜像,那么,Docker首先会从你配置的registry中拉取镜像,就像你手动执行了一次docker pull ubuntu
命令一样; - 随后Docker就会创建一个新的容器,就像你手动执行了
docker container create
命令一样; - Docker分配一个可读写子文件系统给容器,作为容器的最上层。这使得运行着的容器能够创建或修改本地的文件和目录;(注:这一步非常关键,理解起来也比较抽象,涉及到镜像的分层机制,可以说是容器最重要的一个部分)
- Docker创建一个网络接口,把容器与指定的网络进行连接(由于该例子的命令没有指定网络参数,就采用默认的网络模式,即bridge模式;如果docker run命令中指定了
--net
参数,就会选择对应的网络模式)。这一步会给容器分配一个ip地址。(注:这一步则涉及到了容器网络相关的知识,也是非常重要~) - Docker启动容器并执行
/bin/bash
命令。由于容器以交互的方式运行并连接到终端(-i, -t参数),相当于此时我们已经进入到了这个容器里面,可以在里面执行一些其他操作; - 当输入
exit
命令时,表示结束/bin/bash
进程,此时容器停止,但不会被移除。可以执行上述命令重新启动它,当然也可以通过docker rm container_id
删除它。
构建镜像、拉取镜像、提交镜像等命令的执行示意图:
总结:
- 本节内容首先了解了一下云计算的基础概念,虽然在我学习云计算之初,该领域便进入了“容器时代”,但了解SaaS/PaaS/IaaS这些基本概念还是非常有必要;在容器出现之前,都是通过虚拟机来实现资源隔离,因此,从面试的角度来讲,面试官肯定会问你”虚拟机与容器的区别“,而在出现容器技术之后,就有了各种应用”容器化“的故事;
- 随后参照官网简述了“什么是 Docker”,我们平时所说的Docker一般指的就是容器,虽然这并不影响日常工作,但请注意,不要把”Docker“和”容器“的概念混淆。Docker 其实是一个基于容器技术的平台(比如它提供了镜像的分发、管理功能,还提供了REST API和CLI等等);而容器本身只是一个基于Linux内核(namespace & cgroup)的技术,从本质上它就是操作系统的一个进程而已。
- 随后简单了解镜像(image)和容器(container)的概念,并知道了
docker run ...
背后的执行流程,对这个流程理解的越细,就对Docker的各个组件、原理掌握的越深。
参考: