在理解并学习Docker之前,我们得先区分清楚两个概念,虚拟机和容器。
虚拟机:需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。常见的有:VMware , VisualBox等之类。
容器:是和宿主机共享硬件资源及操作系统,可以实现资源的动态分配。容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。容器技术是实现操作系统虚拟化的一种途径,可以让您在资源受到隔离的进程中运行应用程序及其依赖关系。通过使用容器,我们可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响。容器还赋予我们对资源更多的精细化控制能力,让我们的基础设施效率更高。
二者的区别:主要区别在于虚拟化层的位置和操作系统资源的使用方式。
接下来进入正题:
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。Docker 的基础是 Linux 容器(LXC)等技术。在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。
Web 应用的自动化打包和发布。
自动化测试和持续集成、发布。
在服务型环境中部署和调整数据库或其他的后台应用。
从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,可以大大减少编写代码和在生产环境中运行代码之间的延迟。
Docker相比于传统虚拟化方式具有更多的优势:
Docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动。
Docker 需要的资源更少, Docker 在操作系统级别进行虚拟化, Docker 容器和内核交互,几乎没有性能损耗,性能优于通过Hypervisor层与内核层的虚拟化。
Docker 更轻量, Docker 的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境, Docker 运行的镜像数远多于虚拟机数量,对系统的利用率非常高。
与虚拟机相比, Docker 隔离性更弱, Docker 属于进程之间的隔离,虚拟机可实现系统级别隔离。
安全性: Docker 的安全性也更弱。 Docker 的租户 root 和宿主机 root 等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。
可管理性: Docker 的集中化管理工具还不算成熟。
高可用和可恢复性: Docker 对业务的高可用支持是通过快速重新部署实现的。
快速创建、删除:虚拟化创建是分钟级别的, Docker 容器创建是秒级别的, Docker 的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间。
交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化。 Docker 在 Dockerfile 中记录了容器构建过程,可在集群中实现快速分发和快速部署
我们可以从下面这张表格很清楚地看到容器相比于传统虚拟机的特性的优势所在:
特性容器虚拟机启动秒级分钟级硬盘使用一般为MB一般为GB性能接近原生弱于系统支持量单机支持上千个容器一般是几十个了解 Docker 的三个基本概念,就可以大致了解 Docker 的生命周期。
镜像(Image)容器(Container)仓库(Repository)我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变
因为 镜像包含了操作系统完整的 root 文件系统,其体积还是很巨大的,所以引入了 Unios FS 技术,将其设计为分层存储的架构。所以镜像不是那种 ISO 打包文件,镜像是一个虚拟的概念,它是由一组文件系统构成,或者说多层文件系统联合构成。
镜像在构建时,是一层层构建,上一层是下一层的基础,每一层构建结束就不会在被修改,后一层任何修改只会作用在当前层。例如删除上一层文件,不会真的删除该文件,而是会标记删除然后隐藏起来,最终运行容器的时候不会被看见,但是会一直跟随镜像。因此构建镜像时需要小心,不要添加不需要的东西,任何额外的东西都要在本层构建完之前清除。
分层存储使镜像的定制和复用变得容易,可以用之前做好的镜像作为基础层,然后添加新的层,定制自己所需要的东西,构建新的镜像。
镜像(Image)和容器(Conatiner)的关系就像是面向对象的类和实例一样,镜像是静态的定义,容器是镜像运行的实体,容器可以被创建,启动,停止,删除,暂停等。容器的实质是进程,但是又和宿主的进程不同,容器有自己的独立命名空间,因此容器拥有自己 root 文件系统,自己的网络配置,自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。所以好多初学者都会把容器和虚拟机搞混。容器同样和镜像一样使用分层存储,以镜像为基础层,在上面创建了一个容器存储层,是为了容器运行时读写准备的。注意,在容器被删除后,容器存储层保存的任何信息都不会保存,它和容器的生命周期一样,所以任何需要保存的数据 Docker 建议保存在数据卷(Volumes)或者宿主机目录中,这样数据不会随着容器的消失而消失。
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 可以有多个 仓库(Repository),每个仓库可以含多个标签(Tag),每个标签都是一个镜像。
最初我没有搞懂 Docker Registry 和 仓库(Repository),简单来说就是 Docker Registry 是注册服务器,用于管理镜像仓库,起到服务器的作用,仓库(Repository)就是存储镜像,起到存储镜像的作用。默认的 Docker Registry 就是 Docker Hub,其中拥有很多高质量的镜像。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类。
Docker面向对象容器对象镜像类 概念说明Docker 镜像(Images)
Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。
Docker 容器(Container)
容器是独立运行的一个或一组应用,是镜像运行时的实体。
Docker 客户端(Client)
Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
Docker 主机(Host)
一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker Registry
Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。
Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
Docker Machine
Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。