1、Docker背景
在正式开始前,我们首先需要了解容器是什么,以及它为什么会变得如此流行;然后介绍Docker的发展历程,以及为什么需要使用这么一项容器化技术。
Docker出现的背景?
- 环境配置很麻烦,每个机器都要部署,费时费力。
- 发布一个项目,在这个环境好使,换一个不好使,发布包能不能带着环境来打包?
- 配置应用环境不能跨平台。
- 多个应用安装到环境中可能会冲突(比如:端口冲突、软件版本冲突等)。
Docker为了解决上述问题而出现!
- 没用docker前的软件部署流程:软件包–>发布(应用商店)–>下载包->安装可用
- Docker软件部署流程:软件包–>带上环境打包(镜像)–>Docker仓库–>下载发布的镜像–>直接运行镜像
那么什么是容器呢?
容器化是软件开发的一种方法,在这种方法中,程序和它所依赖的组件和集合包,以及相关的环境变量配置文件都会被完全打包成容器镜像,进行单元测试,最后将这个容器部署到服务器的操作系统中。
举个例子:这个与现实生活中的货运集装箱类似,集装箱里面有各种货物(如:衣服、电脑、冰箱等),它们都分门别类的装好了,我们可以通过汽车、火车、飞机来搬运他们。
程序的容器也是一个个标准的单位。无关它们的代码、语言、软件/框架及的依赖关系是怎样的。
Docker 又是什么呢?
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,并于 2013 年 3 月在GitHub上开源。Docker 自开源后受到广泛的关注和讨论,后来由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。
- Docker使用集装箱的思想,自带隔离机制。
- Docker容器可以被理解为一个个轻量级的虚拟机,因为它和虚拟机一样拥有一个被隔离的操作系统实例,用来运行应用程序。
- Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。
2、Docker特点
Docker的特点:
- Docker容器是完全使用沙箱机制(是对进程进行封装隔离,属于操作系统层面的虚拟化技术),容器间相互是不会有任何接口。
- Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后就可以发布到任何Linux、Windows、Mac等机器上实现虚拟化。
- Docker容器性能开销极低,能够更高效的利用系统资源。
- Docker更轻松的维护和扩展,由于Docker使用的分层存储以及镜像的技术,从而可以使得应用重复部分的复用更为容易、维护更新更加简单,我们可以在基础镜像上作进一步扩展来形成新的镜像。
Docker的意义:
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境。
- 对于测试人员:可以直接拿开发时所构建的镜像或通过dockerfile文件构建一个新的镜像开始工作了。
- 对于运维人员:在部署时,可以实现应用的无缝移植。
简单来说,通过docker,我们可以在不同的硬件设备上使用同样的软件环境和配置。在实际的开发场景中,开发人员、测试人员往往不共用一套环境,这导致产品开发完成在转测后出现各种环境不适配、缺少依赖的问题,给测试人员带来了巨大的工作量。而通过docker,开发人员只要定义一个docker镜像,测试人员拉取该镜像并在其中进行相应产品的测试,就可以完全解决运行项目时的环境适配难题。
二、Docker 架构
一个完整的Docker有以下几个部分组成:
- DockerClient客户端
- Docker Daemon守护进程
- Docker Image镜像
- DockerContainer容器
说明:
- Docker 使用客户端/服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
- Docker daemon 是一个常驻在宿主机后台的系统进程(作为服务端在后台运行),负责接收和响应客户请求(如:创建容器、运行容器、分发容器等)。
- Docker 客户端,则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互(用户可以很方便的从本地docker客户端连接到远程docker服务器或远程服务器上运行着的docker守护进程 )。
- Docker客户端 和 Docker服务端既可以运行在一个机器上,也可以运行在不同的机器上。他们之间可通过 socket 或 RESTful API 来进行通信。
- Docker 容器通过 Docker 镜像来创建,容器与镜像的关系类似于面向对象编程中的对象与类的关系。
Docker 几个重要的概念:
-
Docker 镜像(Image)
Docker 镜像(Image)是用于创建 Docker 容器的模板, Docker镜像相当于是一个 root 文件系统。比如:官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。 -
Docker 容器(Container)
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。Docker 容器通过 Docker 镜像来创建。 -
Docker 仓库(Repository)
Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过<仓库名>:<标签>
的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest
作为默认标签。 -
Docker 客户端(Client)
Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。 -
Docker 主机(Host)
一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 -
Docker Machine
Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。
三、Docker详细架构
-
Docker Client
Docker是一个C/S架构程序,通过客户端Client发送请求至服务器或守护进程,而后服务器或守护进程将完成所有的工作后返回结果给客户端。Docker提供了一整套的Restful接口供客户端和服务端通信使用;此外,docker还提供了命令行工具。用户可以很方便的从本地docker客户端连接到远程docker服务器或远程服务器上运行着的docker守护进程。 -
Docker daemon
Docker daemon 守护进程在后台启动一个server,server负载接受docker client发送的请求;接受请求后,server通过路由与分发调度,找到相应的handler来执行请求。
-
Docker server
Docker server专门服务于client,接受并调度分发client的请求。 -
Engine
Engine是docker架构中的运行引擎,也是核心模块。Engine承担着docker容器存储仓库的责任,通过执行job的方式管理操作容器。 -
Job
Job是engine内部最基本的工作执行单元。Docker可以做的每一项工作,都可以抽象为一个job。例如:在容器内部运行一个进程,这是一个job;创建一个新的容器,这是一个job,从Internet上下载一个文档,这是一个job。
Job的设计者,把Job设计得与Unix进程相仿。比如说:Job有一个名称,有参数,有环境变量,有标准的输入输出,有错误处理,有返回状态等。 -
Docker Registry
Docker Registry是一个存储镜像的仓库。而镜像是在容器被创建时,被加载用来初始化容器的文件架构与目录。在docker的运行过程中,docker daemon会与docker registry通信,实现搜索、下载和上传镜像的功能。 -
Graph
Graph是docker已下载镜像的管理者,以及已下载镜像之间关系的记录者。一方面,Graph存储着本地具有版本信息的文件系统镜像,另一方面也通过GraphDB记录着所有文件系统镜像彼此之间的关系。 -
Driver
Driver是驱动模块,主要可以分为三类:graphdriver、networkdriver和execdriver。
1)Graphdriver用于完成镜像的管理,包括存储和获取。
2)Networkdriver用于完成docker容器网络环境的配置。
3)Execdriver则负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。 -
Libcontainer
libcontainer是Docker架构中一个使用Go语言设计实现的库,该库可以不依靠任何依赖,直接访问内核中与容器相关的API。Docker可以直接调用libcontainer实现对容器namespace、cgroups、apparmor、网络设备以及防火墙规则等的操纵。另外,libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。或者说,libcontainer屏蔽了Docker上层对容器的直接管理。 -
Docker Container
Docker容器是docker架构服务最终交付的形式。用户通过指定容器镜像,使得Docker容器可以自定义rootfs等文件系统; 用户通过指定计算资源的配额,使得Docker容器使用指定的计算资源; 用户通过配置网络及其安全策略,使得Docker容器拥有独立且安全的网络环境; 用户通过指定运行的命令,使得Docker容器执行指定的工作。
四、Docker与虚拟机的区别
相同:
- 容器和虚拟机都具有资源隔离的特点。
不同:
- 容器虚拟化的是操作系统(即不同的容器共用宿主机的内核、硬件资源);虚拟机虚拟的是硬件(即不同的虚拟机具有独立操作系统内核、硬件资源)。
- 单机可以支持上千个容器;单机一般只支持几个虚拟机(因为只是获得宿主机的部分硬件资源的)。
- 容器的性能接近原生宿主机;虚拟机的性能较弱(因为只是获得宿主机的部分硬件资源的)。
- 不同容器只能运行同一类型操作系统;不同虚拟机可以运行不同的操作系统。
微信公众号 - 稻哥说编程(RedCode1024)博主,从事程序开发10余年,分享有用的行业解决方案,欢迎留言交流。