Docker 是一种开源的容器化平台,旨在通过轻量级的容器技术实现应用程序及其依赖的快速打包、分发和运行。Docker 的核心特性使其在现代软件开发和运维中具有显著优势,尤其是在微服务架构、持续集成与持续部署(CI/CD)以及云原生应用中。
核心价值Docker 的核心价值在于通过容器化技术解决软件开发、部署和运行中的环境一致性、资源隔离和自动化效率问题,以及推动了DevOps和CI/CD、微服务与云原生的现代化应用架构演进。
环境一致性:镜像标准化,减少“在我机器上能运行”问题传统开发中,开发、测试、生产环境不一致是常态,如操作系统、依赖库版本差异常导致“在我机器上能运行”的问题。
Docker 通过将应用及其所有依赖(如代码、依赖库、系统工具、配置、运行环境等)为打包成一个标准化的“镜像”。镜像在相同架构和内核类型的宿主机上运行结果一致,极大减少了环境差异导致的问题。
资源高效利用(降低成本)传统物理机器部署应用隔离性不足,虚拟机需启动完整的操作系统损耗CPU和内存。而Docker容器则很好的解决了应用隔离与虚拟化损耗问题,使物理机器的资源利用率得到了极大提升。
对于企业来说,提升资源利用率能够显著降低基础设施成本。
快速部署与扩展(提升效率)在软件开发测试阶段,容器可以帮助团队有新成员时可以快速拉起开发环境,基于镜像可以快速的搭建多套相同版本的测试环境。
在软件上线运行阶段,基于容器技术可以快速地将代码部署到生产环境,当出现问题时可以快速回滚到上一个版本镜像,当业务规模增大时可以快速标准化的基于镜像进行业务集群的扩容。
这些场景可以快速、高效且准确的实现业务目标,并且在增效的同时也让运维更简单、更标准、更稳定。
推动云原生与微服务架构演进在DevOps和CI/CD理念中自动化流水线是核心理念,而容器镜像的轻量、可移植性,完美契合自动化流水线。代码提交后,自动构建镜像、自动对镜像运行测试、自动部署镜像到预发环境,大大缩短了发布周期,使得Docker成为CI/CD的利器。
微服务架构理念很早就出现了,但是由于在实际落地时服务拆分变多难以管理,导致维护成本很高。而Docker的轻量化特性使得将单体应用拆分为多个独立的微服务成为可能。每个服务独立部署、独立扩展,不仅架构更灵活,也避免了“牵一发而动全身”的风险。
容器的编排调度催生出很多像 Kuberentes 一样的开源项目,并衍生出 CNCF 云原生计算基金会这样的社区组织,使现代化应用架构向着更加先进的方向演进。
核心特点高效的资源隔离Docker 利用 Linux 内核的命名空间(Namespaces)和控制组(Cgroups)技术,实现了高效的资源隔离。
每个容器都运行在独立的命名空间中,拥有自己的文件系统、网络栈、进程空间等,从而确保了容器之间的隔离性。这种隔离性不仅提高了安全性,还使得多个容器可以在同一主机上并行运行而不会相互干扰。
高资源利用率Docker基于高效的资源隔离,共享宿主机操作系统内核,没有 Hypervisor 层的资源损耗,容器的性能开销极低。
与虚拟机相比,可以更高的提升整体机器的资源利用率。
轻量级与快速的启动由于Docker共享宿主机的操作系统内核,无需启动完整的操作系统。与虚拟机相比,Docker 容器更加轻量,启动时间极短。
通常,Docker 容器可以在几秒钟内启动,而虚拟机可能需要几分钟。这种快速的启动时间使得 Docker 在需要频繁启动和停止的应用场景中具有显著优势。
镜像标准化与可移植性Docker 遵循“一次构建,到处运行”的原则。
Docker创造性的基于分层机制和 UnionFS 文件系统,以及一套格式标准提出了容器镜像的概念,使应用的构建和分发更加高效。每个镜像由多个只读层组成,这些层可以共享和复用,从而减少了存储空间和网络带宽的消耗。
Docker镜像在构建时已经将进程运行所有的依赖全部打包到镜像中,形成一个标准的应用制品,在同种CPU架构的Linux系统上无论是物理机、虚拟机还是云环境,均可以运行。这种跨平台的兼容性使得开发者可以在本地开发环境中构建和测试容器,然后将其无缝部署到生产环境中,无需担心环境差异带来的问题。
强大的生态系统与工具链Docker 不只是一个容器引擎,它还发展出了一整套配套工具,极大地简化了复杂应用的管理。如 Docker Compose、Docker Swarm,以及Docker Hub。特别是 Docker Hub,这里有成千上万的镜像(如 Nginx、MySQL、Redis、Python 等)。你不需要自己从头构建这些软件镜像,只需一条 docker pull 命令就能直接使用,大大降低了环境搭建的门槛。
并且很多云厂商以及开源的项目都会基于Docker进行构建打包分发,或者针对Docker进行产品功能的适配支持,使Docker的生态更加的丰富庞大。
Docker 核心创新Docker 之所以能从众多容器技术中脱颖而出,甚至一度成为“容器”的代名词,是因为它在Linux内核原有技术的基础上,进行了卓越的用户体验封装和镜像机制创新。
“集装箱”式的标准化理念Docker 借鉴了现实世界中物流“集装箱”的概念,将这一思想应用到了软件开发中。
标准化封装。无论里面装的是什么应用(Java、Python、MySQL),只要装进 Docker 这个“集装箱”,对外的接口(运行、停止、网络配置)都是标准化的。
并且容器镜像一旦构建完成,内容就是固定无法进行修改的,任意的修改都会生成新的镜像,这为后续的云原生中 不可变基础设施 概念提供了基础。
镜像分层与写时复制镜像分层与写时复制 (Copy-on-Write) 这是 Docker 最具革命性的创新,彻底改变了应用的打包方式。
Docker 引入了联合文件系统 (Union File System),实现了分层存储于写时复制,让文件能够复用,使容器更加的轻量化。
分层存储 (Layer):Docker 镜像不是单一的大文件,而是由多层只读层组成的。每一层对应 Dockerfile 中的一条指令,且层内容只读。修改某一层会生成新层,适合复用和增量更新。。好处就是层与层之间可以共享。比如你有 10 个基于 Ubuntu 的镜像,宿主机只需要存储一份 Ubuntu 基础层,极大地节省了磁盘空间。
写时复制 (CoW):当容器启动时,Docker 在只读的镜像层之上挂载一个可读写层。容器对文件的修改(新建、修改、删除)都发生在这一层。如果只是读取文件,直接从下层的只读镜像中读取;只有在修改时,才会把文件复制到顶层进行修改。
DockerfileDocker 提供了一种标准化的构建语言——Dockerfile。通过 Dockerfile,你可以用代码定义运行环境(安装什么软件、暴露什么端口、运行什么命令)。
开发人员写好 Dockerfile,构建出镜像。这个镜像在测试环境、生产服务器、同事的电脑上运行结果完全一致,彻底解决了“在我电脑上是好的”这种经典难题。
核心技术Docker 的关键技术在于利用 Linux 内核的 Namespaces 和 Cgroups 实现了轻量级隔离与限制。
Linux Namespace:进程、网络、文件系统等隔离Linux Namespaces 机制提供一种资源隔离方案。PID,IPC,Network等系统资源不再是全局性的,而是属于特定的Namespace。每个Namespace里面的资源对其他Namespace都是透明的。要创建新的Namespace,只需要在调用clone时指定相应的flag。
Linux Namespaces机制为实现基于容器的虚拟化技术提供了很好的基础,LXC(Linux containers), Docker LibContaier 和 RunC 都是利用这一特性实现了资源的隔离。不同container内的进程属于不同的Namespace,彼此透明,互不干扰。
Linux 中使用多种 Namespace 进行系统资源的管理,目前支持:
分类系统调用参数相关内核版本描述Mount namespacesCLONE_NEWNSLinux 2.4.19隔离文件系统挂载点,确保容器看到的目录结构是独立的。UTS namespacesCLONE_NEWUTSLinux 2.6.19隔离主机名和域名信息,容器内和外部的主机名是隔离的,不会互相干扰。IPC namespacesCLONE_NEWIPCLinux 2.6.19隔离了 System V IPC 和 POSIX 消息队列,防止跨容器的进程间通信,但容器内进程仍可通过其他方式通信。PID namespacesCLONE_NEWPIDLinux 2.6.24隔离进程的ID,让容器内的进程只能看到容器内的其他进程(比如你在容器里 ps aux,看不到宿主机的进程)。Network namespacesCLONE_NEWNET始于Linux 2.6.24 完成于 Linux 2.6.29隔离网络资源,拥有独立的网络栈(IP、端口、路由表),这也是为什么多个容器可以同时使用 80 端口的原因。User namespacesCLONE_NEWUSER始于 Linux 2.6.23 完成于 Linux 3.8)隔离用户和用户组的ID,容器内进程只能看到容器内的用户 ID。Linux Cgroup:资源限制(CPU、内存、I/O)Linux CGroup 全称 Linux Control Group, 是 Linux 内核的一个功能,用来限制,控制与分离一个进程组群的资源(如 CPU、内存、磁盘输入输出等)。这个项目最早是由 Google 的工程师在2006年发起(主要是 Paul Menage 和 Rohit Seth),最早的名称为进程容器(process containers)。在2007年时,因为在 Linux 内核中,容器(container)这个名词太过广泛,为避免混乱,被重命名为 cgroup,并且被合并到2.6.24版的内核中去。
Linux CGroup 为系统中所运行任务(进程)的用户定义组群分配资源 — 比如 CPU 时间、系统内存、网络带宽或者这些资源的组合。您可以监控您配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置您的 cgroup。
主要提供了如下功能:
• Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
• Prioritization: 优先级控制,比如:CPU 利用和磁盘 IO 吞吐。
• Accounting: 一些审计或一些统计,主要目的是为了计费。
• Control: 挂起进程,恢复执行进程。
使用 cgroup,系统管理员可更具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和用户分配硬件资源,提高总体效率。
Linux 的 Cgroup 具有不同功能的子系统:
• cpu 子系统,主要限制进程的 cpu 使用率。
• cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
• cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
• memory 子系统,可以限制进程的 memory 使用量。
• blkio 子系统,可以限制进程的块设备 io。
• devices 子系统,可以控制进程能够访问某些设备。
• net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
• freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
Docker 使用 Cgroups 技术对容器的资源使用进行限制和管理,包括:
• CPU 限制:通过 --cpus 参数限制容器的 CPU 使用率。
• 内存限制:通过 --memory 参数限制容器的内存使用量。
• 磁盘 I/O 限制:通过 --blkio-weight 参数限制容器的磁盘 I/O。
UnionFS:镜像分层与存储驱动UnionFS (联合文件系统)实现“分层”,是 Docker 镜像技术的物理基础。它允许将多个文件系统“叠加”在一起,对外呈现为一个统一的文件系统。
UnionFS 是一种为 Linux,FreeBSD 和 NetBSD 操作系统设计的把其他文件系统联合到一个联合挂载点的文件系统服务。它使用 branch 把不同文件系统的文件和目录“透明地”覆盖,形成一个单一一致的文件系统。这些 branches 或者是 read-only 或者是 read-write 的,所以当对这个虚拟后的联合文件系统进行写操作的时候,系统是真正写到了一个新的文件中。看起来这个虚拟后的联合文件系统是可以对任何文件进行操作的,但是其实它并没有改变原来的文件,这是因为 unionfs 用到了一个重要的资管管理技术叫写时复制。
写时复制(copy-on-write,简称 CoW ),也叫隐式共享,是一种对可修改资源实现高效复制的资源管理技术。它的思想是,如果一个资源是重复的,但没有任何修改,这时候并不需要立即创建一个新的资源;这个资源可以被新旧实例共享。创建新资源发生在第一次写操作,也就是对资源进行修改的时候。通过这种资源共享的方式,可以显著地减少未修改资源复制带来的消耗,但是也会在进行资源修改的时候增减小部分的开销。
虽然 Docker 最初确实使用了 UnionFS 的概念,但在现代 Docker 版本中,UnionFS 并不是默认或推荐的存储驱动。Docker 现在支持多种存储驱动(如 overlay2, aufs, btrfs, zfs 等)。在主流的 Linux 发行版(如 Ubuntu, CentOS)中,默认通常使用的是 OverlayFS(特别是 overlay2)。
小结Docker 设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后一个标准化组件是用户的app)。这也就是基于docker的PaaS产品的原型。
容器技术虽然解决了虚拟化本身的损耗问题,但是有很长一段时间没有成为主流。主要原因是不好用,学习和使用成本比较高,直到 Docker 的出现。Docker 并不是新技术,而是使用了一种创新的方式来时整合使用已有的技术。Linux 命名空间、CGroup和 UnionFS 三大技术支撑了目前 Docker 的实现。Docker 软件将虚拟化的技术进行封装了人们常用的指令工具,屏蔽了底层 Cgroup、Namespace、UnionFS等具体的技术细节,使其推广和使用成本大大降低。