Docker 概述
- 1. Docker 的主要目标
- 2. 使用Docker 容器化封装应用程序的意义
- 3. 容器和虚拟机技术比较
- 4. 容器和虚拟机表现比较
- 5. Docker 的组成
- 6. Namespace
- 7. Control groups
- 8. 容器管理工具
- 9. docker 的优缺点
- 10. 容器的相关技术
docker 官网: http://www.docker.com
帮助文档链接: https://docs.docker.com/
docker 镜像: https://hub.docker.com/
docker 中文网站: http://www.docker.org.cn/
Docker 是一个可以将应用程序及其依赖打包到几乎可以在任何服务器上运行的容器的工具。
容器是一种 IT 技术。容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装 箱一样,把你的应用装起来。这样,应用与应用之间就有了边界而不会相互干扰;同时装在沙盒里面的应 用,也可以很方便的被搬来搬去,这也是 PaaS 想要的最理想的状态(可移植性,标准化,隔离性)。
容器是软件工业上的集装箱的技术,集装箱的标准化,减少了包装成本,大大提高货物运输和装卸效 率,是传统运输行业的重大变革。早期的软件项目中软件更新,发布低效,开发测试发布周期很长,很 难敏捷。有了容器技术,就可以利用其标准化的特点,大幅提高生产效率。
容器技术是虚拟化、云计算、大数据之后的一门新兴的并且是炙手可热的新技术, 容器技术提高了硬件 资源利用率、 方便了企业的业务快速横向扩容(可以达到秒级快速扩容)、 实现了业务宕机自愈功能 (配合K8S可以实现,但OpenStack无此功能),因此未来数年会是一个容器愈发流行的时代 ,这是 一 个对于 IT 行业来说非常有影响和价值的技术,而对于IT行业的从业者来说, 熟练掌握容器技术无疑是一 个很有前景的行业工作机会。
Docker (码头工人)是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司(后由于 Docker 开 源后大受欢迎就将公司改名为 Docker Inc ,总部位于美国加州的旧金山)内部的一个开源的 PAAS 服务 (Platform as a ServiceService )的业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入 了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
Docker 是基于 Linux 内核实现,Docker 最早采用 LXC 技术 ,LXC 是 Linux 原生支持的容器技术 ,可 以提供轻量级的虚拟化 ,可以说 docker 就是基于 LXC 发展起来 的,提供 LXC 的高级封装,标准的配 置方法,在LXC的基础之上,docker提供了一系列更强大的功能。而虚拟化技术 KVM(KernelKernelbased Virtual Machine Machine) 基于 模块实现, 后来Docker 改为自己研发并开源的 runc 技术运行 容器,彻底抛弃了LXC。
Docker 相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端/服务端架构,使用远程API来 管理和创建容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是 build(构建)、ship(运输)、 run(运行),Docker遵从apache 2.0协议,并通过(namespace及cgroup 等)来提供容器的资源隔离与安全保障等,所以Docke容器在运行时不需要类似虚拟机(空运行的虚拟 机占用物理机6-8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机.类似于VM但是在原理和应用上和VM的差别还是很大的,并且docker的专 业叫法是应用容器(Application Container)。
1. Docker 的主要目标
Build, Ship and Run Any App, Anywhere,即通过对应用组件的封装(Packaging)、分发 (Distribution)、部署(Deployment)、运行(Runtime)等生命周期的管理,达到应用组件级别的 “一次封装,到处运行”。这里的应用组件,既可以是一个Web应用,也可以是一套数据库服务,甚至是 一个操作系统。将应用运行在Docker 容器上,可以实现跨平台,跨服务器,只需一次配置准备好相关的 应用环境,即可实现到处运行,保证研发和生产环境的一致性,解决了应用和运行环境的兼容性问题, 从而极大提升了部署效率,减少故障的可能性
2. 使用Docker 容器化封装应用程序的意义
-
统一基础设施环境-docker环境
- 硬件的组成配置
- 操作系统的版本
- 运行时环境的异构
-
统一程序打包(装箱)方式-docker镜像
- java程序
- python程序
- nodejs程序
- 统一程序部署(运行)方式-docker容器
- java-jar…→ docker run…
- python manage.py runserver… → docker run…
- npm run dev … → docker run…
3. 容器和虚拟机技术比较
- 传统虚拟机是虚拟出一个主机硬件,并且运行一个完整的操作系统 ,然后在这个系统上安装和运行软 件
- 容器内的应用直接运行在宿主机的内核之上,容器并没有自己的内核,也不需要虚拟硬件,相当轻量化
- 每个容器间是互相隔离,每个容器内都有一个属于自己的独立文件系统,独立的进程空间,网络空间,用 户空间等,所以在同一个宿主机上的多个容器之间彼此不会相互影响
4. 容器和虚拟机表现比较
- 资源利用率更高: 开销更小,不需要启动单独的虚拟机OS内核占用硬件资源,可以将服务器性能压榨 至极致.虚拟机一般会有5-20%的损耗,容器运行基本无损耗,所以生产中一台物理机只能运行数十个 虚拟机,但是一般可以运行数百个容器
- 启动速度更快: 可以在数秒内完成启动
- 占用空间更小: 容器一般占用的磁盘空间以MB为单位,而虚拟机以GB
- 集成性更好: 和 CI/CD(持续集成/持续部署)相关技术结合性更好,实现打包镜像发布测试可以一 键运行,做到自动化并快速的部署管理,实现高效的开发生命周期
使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操 作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能 损耗,我们创建虚拟机的目的是为了运行应用程序,比如Nginx、PHP、Tomcat等web程序,使用虚拟 机无疑带来了一些不必要的资源开销,但是容器技术则基于减少中间运行环节带来较大的性能提升。
根据实验,一个运行着CentOS的KVM虚拟机启动后,在不做优化的情况下,虚拟机自己就需要占用 100~200 MB内存。此外,用户应用运行在虚拟机里面,它对宿主机操作系统的调用就不可避免地要经 过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗非常 大。
比如: 一台96G内存的物理服务器,为了运行java程序的虚拟机一般需要分配8G内存/4核的资源,只能 运行13台左右虚拟机,但是改为在docker容器上运行Java程序,每个容器只需要分配4G内存即可,同样 的物理服务器就可以运行25个左右容器,运行数量相当于提高一倍,可以大幅节省IT支出,通常情况下 至少可节约一半以上的物理设备
5. Docker 的组成
- Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机, node节点
- Docker 服务端(Server): Docker守护进程,运行docker容器
- Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合
- Docker 仓库(Registry): 保存镜像的仓库,官方仓库: https://hub.docker.com/,可以搭建私有仓库 harbor
- Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中 的程序启动后生成的进程
6. Namespace
namespace是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间被部署在内核,各 个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机 的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内 实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统空 间、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:
Pid namespace
- 不同用户的进程就是通过Pid namespace 隔离开的,且不同namespace 中可以有相同Pid。
- 有了Pid namespace,每个namespace 中的Pid 能够相互隔离:
net namespace
- 网络隔离是通过net namespace 实现的,每个net namespace 有独立的network devices,IP,addresses,IP routing tables, /proc/net 目录。
- Docker 默认采用veth 的方式将container 中的虚拟网卡同host 上的一个docker bridge: docker0连接在一起。
ipc namespace
- Container 中进程交互还是采用linux 常见的进程间交互方法(interprocess communication -IPC),包括常见的信号量、消息队列和共享内存。
- container 的进程间交互实际上还是host上具有相同Pid namespace 中的进程间交互,因此需要在IPC资源申请时加入namespace 信息-每个IPC资源有一个唯一的32 位ID。
mnt namespace
- mnt namespace 允许不同namespace 的进程看到的文件结构不同,这样每个namespace 中的进程所看到的文件目录就被隔离开了
uts namespace
- UTS(“UNIX Time-sharing System") namespace允许每个container 拥有独立的hostname 和domain name,使其在网络上可以被视作一个独立的节点而非Host 上的一个进程。
user namespace
- 每个container 可以有不同的user 和group id,也就是说可以在container 内部用container 内部的用户执行程序而非Host 上的用户。
7. Control groups
Linux Cgroups的全称是Linux Control Groups,是Linux内核的一个功能.最早是由Google的工程师(主 要是Paul Menage和Rohit Seth)在2006年发起,最早的名称为进程容器(process containers)。在 2007年时,因为在Linux内核中,容器(container)这个名词有许多不同的意义,为避免混乱,被重命 名为cgroup,并且被合并到2.6.24版的内核中去。自那以后,又添加了很多功能。
如果不对一个容器做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug 程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资 源分配限制,比如CPU、内存等
Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽 等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操 作)。
Cgroups在内核层默认已经开启,从CentOS 和 Ubuntu 不同版本对比,显然内核较新的支持的功能更 多。
8. 容器管理工具
有了以上的chroot、namespace、cgroups就具备了基础的容器运行环境,但是还需要有相应的容器创 建与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需 要解决,于是容器管理技术出现了。目前主要是使用docker,早期使用 LXC。
Docker 相当于增强版的LXC,功能更为强大和易用,也是当前最主流的容器前端管理工具
Docker 先启动一个容器也需要一个外部模板,也称为镜像,docke的镜像可以保存在一个公共的地方共 享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把 其提交为一个镜像,一个镜像可以被启动为多个容器。
Docker的镜像是分层的,镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一 个容器后会生成一个可写层,其写入的数据会复制到宿主机上对应容器的目录,但是容器内的数据在删 除容器后也会被随之删除。
Podman 和docker不同之处
- docker 需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman 不 需要
- 启动容器的方式不同:
- docker cli 命令通过API跟 docker Engine 才会调用 Docker Engine(引擎) 交互告诉它我想创建一个container,然后 container的process(进程)不会是 OCI container runtime(runc) 来启动一个container。这代表 Docker CLI 的 Engine 的 child process 。 child process(子进程),而是
- Podman 是直接给 container process 直接是 Docker OCI containner runtime(runc) 进行交互来创建container的,所以 podman 的 child process 。
- 因为docke有docker daemon,所以docker启动的容器支持–restart 策略,但是podman不支持
- docker需要使用root用户来创建容器。 这可能会产生安全风险,尤其是当用户知道docker run命 令的–privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行
- docker在Linux上作为守护进程运行扼杀了容器社区的创新。 如果要更改容器的工作方式,则需要 更改docker守护程序并将这些更改推送到上游。 没有守护进程,容器基础结构更加模块化,更容 易进行更改。 podman的无守护进程架构更加灵活和安全。
9. docker 的优缺点
优点
- 快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上
- 高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性 能和效率
- 节省开支: 提高服务器利用率,降低IT支出
- 简化配置: 将运行环境打包保存至容器,使用时直接启动即可
- 环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问 题
- 快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将 应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
- 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横 向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响
缺点
- 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
- 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和 繁琐
- 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重 复浪费
10. 容器的相关技术
容器 runtime
runtime是真正运行容器的地方,因此为了运行不同的容器runtime需要和操作系统内核紧密合作相互在 支持,以便为容器提供相应的运行环境
目前Docker默认的runtime是runc
容器管理工具
管理工具连接runtime与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给 runtime执行。
镜像仓库 Registry
统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库
容器编排工具
当多个容器在多个主机运行的时候,单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台 主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有 一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎
容器编排通常包括容器管理、调度、集群定义和服务发现等功能
- Docker compose : docker 官方实现单机的容器的编排工具
- Docker swarm: docker 官方开发的容器编排引擎,支持overlay network
- Mesos+Marathon: Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内 核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的集 群组员调度平台,mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能
ocker compose : docker 官方实现单机的容器的编排工具 - Docker swarm: docker 官方开发的容器编排引擎,支持overlay network
- Mesos+Marathon: Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内 核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的集 群组员调度平台,mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能
- Kubernetes: google领导开发的容器编排引擎,内部项目为Borg,且其同时支持 docker 和 CoreOS,当前已成为容器编排工具事实上的标准