官网
Docker 是一种开源的容器化平台,用于开发、部署和运行应用。它通过将应用程序及其依赖项打包到称为“容器”的单一包中,使得应用能够在任何环境下运行,不受底层系统的限制。Docker提供了一种标准化的软件交付方式,使得应用在开发、测试和生产环境中的运行更加一致。
Docker的核心概念
-
镜像(Image):Docker镜像是容器的“模板”,包含了操作系统、应用程序以及相关依赖库。镜像是只读的,用于创建和运行容器。
-
容器(Container):容器是镜像的一个运行实例,是一个隔离的进程环境,拥有独立的文件系统、网络等资源。一个镜像可以创建多个容器,每个容器之间是相互隔离的。
-
Dockerfile:Dockerfile是一个文本文件,定义了如何构建Docker镜像。它包含了一系列指令,用于描述镜像的构建步骤,例如选择基础镜像、安装依赖、复制文件、设置环境变量等。
-
仓库(Registry):Docker仓库用于存储和分发Docker镜像,类似于代码的版本控制系统。Docker Hub是官方的公共镜像仓库,用户也可以搭建私有仓库。
Docker的底层架构与组件
Docker的底层架构主要由以下几个核心组件组成:
Docker Daemon(守护进程):
- Docker Daemon是Docker的后台进程,负责管理容器的生命周期、构建和运行镜像。它接受客户端(CLI)命令并执行相应操作。
Docker CLI:
- Docker CLI是Docker的命令行界面,用于与Docker Daemon进行通信,执行容器的启动、停止、删除等操作。
Containerd:
- Containerd是一个容器管理的守护进程,负责管理容器的生命周期。它是Docker的一部分,但也可以作为独立组件使用,直接与OCI(Open Container Initiative)兼容。
RunC:
- RunC是一个轻量级的、符合OCI标准的容器运行时工具。RunC的核心作用是创建和启动容器,通过Namespace、Cgroups等
- Linux内核特性实现容器的隔离与资源控制。
Libnetwork:
- Libnetwork是Docker的网络管理库,用于处理容器的网络连接,包括创建虚拟网络、网络隔离等操作。
图像和存储管理:
Docker支持多种存储驱动(如OverlayFS、AUFS、Device Mapper等),用于管理镜像的分层存储结构。每一层只保存了增量数据,这种分层存储可以提高资源利用率并减少冗余。
Docker 使用客户端-服务器架构。Docker 客户端与 Docker 守护程序通信,后者负责构建、运行和分发 Docker 容器的繁重工作。Docker 客户端和守护程序可以在同一系统上运行,或者您可以将 Docker 客户端连接到远程 Docker 守护程序。Docker 客户端和守护程序使用 REST API、通过 UNIX 套接字或网络接口进行通信。另一个 Docker 客户端是 Docker Compose,它允许使用由一组容器组成的应用程序。
Docker的底层原理
Docker的底层原理主要依赖于Linux内核的几个关键技术,包括Namespace、Cgroups、Union File System等,这些技术实现了容器的隔离、资源管理和文件系统支持。
-
Namespace(命名空间)
Namespace是Linux内核提供的资源隔离技术,它允许系统资源(如进程ID、网络、文件系统等)被隔离到独立的命名空间中。不同命名空间内的资源是相互独立的,从而使得一个容器中的进程无法影响另一个容器中的进程。Docker主要使用了以下几种Namespace:- PID Namespace:隔离进程ID,使得每个容器中的进程彼此独立。
NET Namespace:隔离网络资源,如网卡、IP地址、端口等,使得容器拥有独立的网络栈。
IPC Namespace:隔离进程间通信(如信号、消息队列等),确保容器间通信安全。
Mount Namespace:隔离文件系统挂载点,每个容器可以拥有独立的文件系统视图。
UTS Namespace:隔离主机名和域名,使得容器可以设置自己的主机名。
- PID Namespace:隔离进程ID,使得每个容器中的进程彼此独立。
-
Cgroups(Control Groups)
Cgroups是Linux内核提供的资源管理功能,可以限制和隔离进程组使用的资源(如CPU、内存、磁盘I/O等)。在Docker中,Cgroups用于限制每个容器的资源使用,确保系统稳定。比如,可以设置一个容器的CPU最大使用率不超过50%、内存不超过1GB等,从而避免单个容器过度占用资源影响其他容器。 -
Union File System(联合文件系统)
Docker的镜像由多层只读层叠加而成,这种分层结构依赖于Union File System的支持。常见的联合文件系统有AUFS、OverlayFS等。每层镜像都只记录了文件系统的增量,只有在容器运行时创建一个可写层。分层文件系统使得镜像可以高效共享、重复利用,提高了存储空间的利用率。 -
容器镜像的分层结构与存储管理
Docker镜像的分层结构使得不同镜像可以共享相同的底层资源。在镜像构建时,Docker会为每个操作创建一个新的层,这些层按顺序叠加构成完整的镜像。在容器启动时,Docker会在镜像的顶部添加一个可写层,即“容器层”,以便容器可以对文件系统进行读写操作。
Docker的运行流程
构建镜像:根据Dockerfile构建镜像,镜像分为多个只读层,每层对应Dockerfile的一条指令。
启动容器:从镜像创建容器实例,并为容器创建一个可写层。
隔离资源:启动容器时,Docker通过Namespace隔离容器的进程、网络、文件系统等资源。
分配资源:Docker通过Cgroups为容器分配资源,并监控其资源使用情况。
容器网络:Docker使用Libnetwork为容器创建网络连接,实现容器间通信和网络隔离。
文件系统管理:Docker使用联合文件系统挂载镜像层,并为容器提供可写层。
Docker的优势与应用场景
一致性:Docker打包了应用和依赖,确保在不同环境中运行的一致性,解决了“运行在我电脑上”的问题。
资源高效:相比虚拟机,容器不需要完整的操作系统和硬件模拟,启动速度快,资源占用少。
弹性伸缩:通过编排工具(如Kubernetes)管理容器集群,容器化应用易于实现水平扩展和自动恢复。
快速交付:Docker简化了软件的开发、测试、部署流程,使得开发、测试、运维团队之间的协作更加高效。
容器与虚拟机 (VM)
简单来说,虚拟机是一个完整的操作系统,拥有自己的内核、硬件驱动程序、程序和应用程序。启动虚拟机只是为了隔离单个应用程序,这会带来很大的开销。
容器只是一个独立的进程,其中包含运行所需的所有文件。如果运行多个容器,它们都共享同一个内核,这样您就可以在更少的基础设施上运行更多的应用程序。
结合使用虚拟机和容器
容器和虚拟机经常一起使用。例如,在云环境中,配置的机器通常是虚拟机。但是,具有容器运行时的虚拟机可以运行多个容器化应用程序,而不是配置一台机器来运行一个应用程序,从而提高资源利用率并降低成本。
容器和镜像的关系
容器是一个独立的进程,它从哪里获取文件和配置?如何共享这些环境?这就是容器镜像发挥作用的地方!容器镜像是一个标准化包,其中包含运行容器所需的所有文件、二进制文件、库和配置。
对于 PostgreSQL映像,该映像将打包数据库二进制文件、配置文件和其他依赖项。对于 Python Web 应用,它将包括 Python 运行时、应用代码及其所有依赖项。
镜像有两个重要原则:
-
镜像是不可变的。镜像一旦创建,就无法修改。只能创建新镜像或在其上添加更改。
-
容器镜像由层组成。每层代表一组添加、删除或修改文件的文件系统更改。
可以理解为镜像就是一个流水线工厂,容器就是最终加工出来的产品