1、什么是docker?
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。
简单地说就是,docker是一种虚拟化技术的产品,属于一种“容器”。“容器”这个东西有点像虚拟机,但是有很大的不同。理解容器和虚拟机的区别是很重要的一点。下面做一下简单的对比区分。
一句话概括容器:容器就是将软件打包成标准化单元,以用于开发、交付和部署。
Docker与虚拟机对比
- Docker有着比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在Cpu、内存利用率上Docker将会在效率上有明显优势。
- Docker利用的是宿主机的内核,而不需要Guest OS,因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统,避免了引导、加载操作系统内核这个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的,而Docker由于直接利用宿主机的操作系统则省略了这个过程,因此新建一个Docker容器只需要几秒钟。
| Docker容器 | 虚拟机(VM) | |
| 操作系统 | 与宿主机共享OS | 宿主机OS上运行宿主机OS |
| 存储大小 | 镜像小,便于存储与传输 | 镜像庞大(vmdk等) |
| 运行性能 | 几乎无额外性能损失 | 操作系统额外的cpu、内存消耗 |
| 移植性 | 轻便、灵活、适用于Linux | 笨重、与虚拟化技术耦合度高 |
| 硬件亲和性 | 面向软件开发者 | 面向硬件运维者 |
2、Docker的三个基本概念
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
简单来说,Docker的image可以理解是一个只读的静态模板,类似于我们在装系统的时候用到的.iso文件;而container则相对而言是一个动态的instance,或者说可以理解为我们装好了系统之后的某一台计算机,可以开机,关机,重启等等,也可以被格式化(删除)。如果我们想在另一台计算机上复现我这台计算机的系统,则可以ghost一个新的镜像,然后去安装(虽然这种操作通常不行,因为底层硬件的驱动可能不匹配)。
镜像(Image)
操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(Image),就相当于是一个root文件系统。
现在重新理解一下我们使用一个linux系统的过程。我们开机的时候,linux内核会先启动,然后挂载root文件系统作为用户空间;而Docker镜像就相当于是一个root文件系统,每开一个就有了一个独立的用户空间。
Docker设计时,就充分利用Union FS的技术,将其设计为分层存储的架构。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
容器(Container)
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的类,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。
前面讲过镜像使用的是分层存储,容器也是如此。
按照Docker最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
所谓“绑定宿主目录”,就是在run一个container的时候使用-v命令把宿主机的存储目录映射进container。我们可以这样理解,image是分层存储的,我们每做一次修改就会在原本的Image存储层上多搭一层,记录这个更改;而新搭的这层是静态、且可以持久化存储的。Container也是相同额存储架构,但是每次修改新搭的一层是动态的,而且并不是持久化存储的;当容器被remove,或者重启计算机(内存断电)之后,container没了,相应的这些容器存储层也没了。因此要尽量保持容器存储层无状态化,所有的contain里产生的数据(比如container里的程序的运行结果)都要通过挂载宿主目录直接写进宿主硬盘里。
仓库(Repository)
我们可以把构建后的镜像上传到服务器,从而可以在任何地方使用到这个镜像。
一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。
如果不给出标签,将以latest作为默认标签。
最常使用的Registry公开服务是官方的Docker Hub ,这也是默认的Registry,并拥有大量的高质量的官方镜像,网址为:http://hub.docker.com