docker 的原理

Docker,这个近年来在软件开发和运维领域广受追捧的技术,究竟是什么?它如何实现资源隔离?它的运行方式是否类似于 Java 虚拟机(JVM)?Docker 的组成又是什么?本文将一一解答这些问题。

1. Docker 是什么?

Docker 可以被看作是一个轻量级的集装箱,它能够将应用程序及其所需的环境和依赖项打包在一起。这个集装箱在任何支持 Docker 的机器上都能运行,无论它是物理服务器、虚拟机还是云平台。这样,应用程序就可以在 “不同的环境(软硬件环境)” 中保持一致的行为,不用担心环境差异导致的问题(如无法运行、崩溃、错误)。

从系统的角度去思考,Docker 是一个被隔离的进程,它能够将应用程序运行所需的环境和资源与宿主机上的其他应用程序隔离开来。这种隔离主要体现在以下几个方面:

  1. 文件系统隔离:Docker 容器有自己的文件系统,与宿主机的文件系统是分开的。这意味着容器内的应用程序只能访问到分配给它的文件和目录,而不会影响到宿主机上的其他文件。
  2. 网络隔离:每个 Docker 容器可以有自己的网络接口和 IP 地址。这样,容器内的应用程序就像是在互联网上拥有自己的独立地址一样,可以与其他容器或外部网络进行通信,而不会干扰到宿主机或其他容器的网络。
  3. 进程隔离:虽然 Docker 容器共享宿主机的操作系统内核,但容器内的进程是独立的。容器内的应用程序运行在自己的进程空间中,不会直接影响到宿主机或其他容器的进程。
  4. 资源隔离:Docker 可以为每个容器分配一定的资源配额,比如 CPU 和内存使用量。这意味着即使容器内的应用程序出现问题,消耗了大量资源,也不会影响到宿主机或其他容器的资源使用。

那么,Docker 是如何实现资源隔离的呢?Docker 利用了 Linux 内核的命名空间(Namespaces)和控制组(Cgroups)技术。命名空间允许 Docker 创建隔离的文件系统、网络接口和用户空间,每个 Docker 容器都像是在运行自己的独立操作系统。而控制组则允许 Docker 限制和监控容器使用的物理资源,如 CPU 和内存。

2. Docker 的运行方式是类似 JVM 吗?

Docker 的运行方式与 JVM 有所不同。JVM 提供了一个完整的运行时环境,Java 程序被编译成字节码后,在 JVM 上运行。JVM 负责管理内存、垃圾回收和安全性等。

相比之下,Docker 并不提供一个独立的运行时环境。相反,Docker 容器共享宿主机的操作系统内核,只隔离了用户空间。这意味着 Docker 容器内的应用程序直接运行在宿主机的内核上,但只能访问容器内的环境和资源。Docker 通过启动一个隔离的进程来运行应用程序,这个进程有自己独立的文件系统、网络和资源限制。

3. Docker 的组成?

Docker 使用客户端 - 服务端架构,即客户端 (Docker client) 与服务端 (Docker daemon) ,服务端的作用是完成容器的构建、运行和分发,客户端可以和服务端运行在同一主机上,也可以远程连接到不同主机的服务端。客户端与服务端通过 REST API、UNIX sockets 或者网络接口沟通。另一个客户端是 Docker Compose,它包含一个应用程序的所有容器。

  • Docker 守护进程:守护进程(dockerd)是后台服务,负责管理 Docker 对象,如镜像、容器、网络和卷。它通过 REST API 与 Docker 客户端通信。
  • Docker 客户端:用户通过 Docker 命令行界面(CLI)或 API 与 Docker 守护进程交互。客户端发送命令,如 docker run 来启动新容器。
  • Docker Desktop:通过界面化的方式构建分析容器化的应用或者微服务,包括服务端、客户端、Docker Compose、Docker Content Trust, Kubernetes, and Credential Helper
  • Docker registries:Docker 的注册表存储了 Docker 镜像,可以是 Docker Hub 官方镜像库,也可以是其他库。当使用 docker pull 或者 docker run 时,从配置的镜像库拉取镜像,docker push 则会将自己镜像推送到自定义镜像库

基于以上的工具,使用 Docker 时,还通常涉及镜像、容器、网络、容量及插件

  • Docker 镜像:镜像是一个只读的模板,包含了运行应用程序所需的代码、运行时、库、环境变量和配置文件。镜像是创建容器的基础。
  • Docker 容器:容器是镜像的运行实例。每个容器都是隔离的,运行自己的进程,并且只能访问分配给它的资源。

外部应用程序使用 Docker 的方式多种多样:

  • 直接使用 CLI:用户可以通过命令行直接启动和管理容器。
  • 使用 Docker Compose:对于多容器应用,可以使用 Docker Compose 来定义和运行服务。通过一个 YAML 文件来配置应用的服务,然后使用一个单一的命令 docker-compose up 来启动所有服务。
  • 集成到 CI/CD 流程:Docker 可以集成到持续集成和持续部署(CI/CD)的流程中。开发人员可以将应用代码和 Dockerfile 推送到版本控制系统,然后自动触发构建流程,生成新的 Docker 镜像,并部署到测试或生产环境
  • 使用 Docker SDKs:开发者可以在应用程序中直接使用 Docker SDKs 来管理容器。
  • 容器编排工具:对于大规模的容器部署,可以使用容器编排工具,如 Kubernetes、Docker Swarm 或 OpenShift。这些工具可以帮助管理大规模的容器集群,提供服务发现、负载均衡、自我修复等功能。

总结来说,Docker 是一个强大的工具,它通过轻量级的容器化技术,实现了应用程序的隔离和可移植性。它的运行机制与 JVM 不同,更依赖于宿主机的内核和资源。Docker 的组成和使用方式为开发者和运维人员提供了灵活、高效的方式来构建、部署和管理应用程序。

参考:

  1. What is Docker? | Docker Docs
  2. 一文读懂 Docker 原理 - Blogs - 廖雪峰的官方网站