Docker 是一个开源的容器化平台,它允许我们将应用程序及其所有依赖项打包在一起,形成所谓的“容器”。这确保了我们的应用无论是在开发、测试还是生产环境中,都能无缝运行。简单来说,Docker 是一个旨在通过使用容器来简化应用创建、部署和运行的工具。
什么是容器化?
容器化 (Containerization) 是一种基于操作系统(OS)层面的虚拟化技术。
- 它在用户空间内创建多个相互隔离的虚拟单元,这些单元被称为容器。
- 所有容器共享同一个主机操作系统的内核。
- 容器之间的隔离是通过以下机制实现的:
- 命名空间:用于实现进程、网络和文件系统的隔离。
- 资源控制机制:用于限制 CPU 和内存的使用。
虚拟化 vs 容器化
!image
为了真正理解 Docker,我们需要先了解它之前的技术:虚拟机。
- 虚拟机: 它是对硬件进行虚拟化。每个虚拟机都在一个称为 Hypervisor 的软件层之上运行一个完整的操作系统。这是一个非常“重”的过程;一个虚拟机可能占用数 GB 的空间,并且需要几分钟才能启动。
- 容器: 它是对操作系统进行虚拟化。容器共享主机的操作系统内核,但将应用程序隔离在“用户空间”中。这是一个非常“轻”的过程;容器通常只占用 MB 级别的空间,并且可以在毫秒级内启动。
虚拟机
—
硬件级(重量级)
分钟级
吉字节
低(依赖特定的 Hypervisor)
Docker 架构
Docker 采用的是 客户端-服务器 架构。它不仅仅是一个单一的程序,而是一个由三个相互通信的组件构成的系统。
- Docker 客户端: 也就是我们经常在命令行中输入的命令工具 (
docker)。 - Docker 守护进程: 运行在主机上的后台进程,负责处理繁重的任务(如构建、运行和分发容器)。
- Docker 注册表: 存储 Docker 镜像的地方(类似于 Docker Hub)。
工作流程如下:
- 当我们输入 docker build 时 -> 客户端向守护进程发送请求 -> 守护进程构建一个镜像。
- 当我们输入 docker run 时 -> 客户端向守护进程发送请求 -> 守护进程启动一个容器。
!<a href="https://media.geeksforgeeks.org/wp-content/uploads/20260114153314494879/dockerarchitecture.webp">dockerarchitecture
Docker 的核心组件
Docker 的主要组件包括:Docker 客户端和服务器、Docker 镜像、Dockerfile、Docker 注册表 以及 Docker 容器。让我们在下面的章节中详细了解一下这些组件:
Docker 客户端和服务器
Docker 采用的是客户端-服务器架构。Docker 守护进程(服务器)包含了所有的容器。它通过 CLI 或 REST API 接收来自 Docker 客户端的请求,并进行相应的处理。Docker 客户端和守护进程可以运行在同一台主机上,也可以运行在不同的主机上。
Docker 镜像
Docker 镜像是一个只读的、静态的模板,其中包含了运行应用程序所需的代码、库、依赖项、工具以及其他配置文件。
- 核心概念:分层架构。 镜像并不是一个庞大的单块文件,而是由多层构建而成的。
- 例如,当我们拉取一个像 nginx 这样的镜像时,我们实际上不是在下载一个大文件,而是在下载多个小层(比如,一层是基础操作系统,一层是 Nginx 软件,一层是配置文件)。
- 不可变性: 一旦镜像构建完成,就无法再被修改。如果我们需要修复 bug,我们不能直接给镜像“打补丁”,而是需要修改 Dockerfile 并重新构建一个新的镜像。
Dockerfile
Dockerfile 是一个纯文本文件,包含了一系列按顺序排列的指令(命令)。Docker 守护进程会读取这些指令来自动构建镜像。我们可以把它看作是基础设施的“源代码”。Dockerfile 中的每一行都会在镜像中创建一个新的“层”。Docker 会从上到下读取该文件。
- FROM:起点(例如
FROM ubuntu:20.04)。这是构建的基础。 - RUN:在构建过程中执行命令(例如
RUN apt-get install python3)。这将软件“烘焙”到镜像中。 - COPY:将我们本机的实际代码移动到镜像中。
- CMD:容器启动时运行的默认命令(例如
CMD ["python", "app.py"])。
Docker 容器
容器是镜像的一个运行实例。它是实际“活着”的进程。当我们启动一个容器时,Docker 会获取只读的镜像,并在其顶部添加一个薄的读写层。
核心概念: