Docker 入门
了解虚拟机和容器的概念及其区别。掌握 Docker 的架构,并清楚在什么情况下应使用容器,以及在什么情况下使用虚拟机更为合适。
开始使用 Docker
要理解当下,我们必须先回顾过去,了解我们是如何走到今天的。在过去,应用程序运行在办公室后端的物理服务器上。
大多数情况下,每个服务器只运行一个应用程序。企业会提前订购服务器机架和其他硬件,以应对大规模部署的需求。开发速度非常缓慢。
部署新应用程序耗时且效率低下,需要大量配置,通常需要数月才能完成。那时的应用程序是为有限数量的人设计和构建的,通常仅限于单一办公地点。
虚拟机
随着世界日益互联,竞争愈发激烈,仅靠在后端物理服务器上运行应用程序已无法满足需求。在此背景下,虚拟化技术应运而生,并迅速成为大多数企业的救星。
与每个服务器只运行一个应用不同,虚拟化技术将一台物理服务器的硬件资源划分为多个虚拟机,从而实现在单台服务器上运行多个应用程序。
虚拟机的优势在于更易于使用,对企业的成本也更低。它们提供了一定程度的灵活性,但仍存在一些问题。
虚拟化存在的问题包括:
- 每个虚拟机都需要独立的操作系统(OS),这会占用额外的内存、RAM 和存储空间,这些资源本可用于支持其他业务应用。
- 某些操作系统需要许可证。
- 虚拟机启动缓慢,耗时较长。
- 虚拟机不具备可移植性,难以在不同云平台之间迁移工作负载。
显然,虚拟化并非适用于所有场景,因为在某些情况下,灵活性和可移植性更为关键。这时容器化技术便登场了。
与通过虚拟机隔离计算资源不同,容器化采用“容器”这一概念来实现软件的隔离与封装。
那么,什么是容器呢?
容器
Docker 平台团队对容器的定义如下:
容器是一种标准的软件单元,它将代码及其运行所需的所有依赖项打包在一起,能够快速、可靠地从一个计算环境迁移到另一个环境。
在没有容器或虚拟化技术的情况下,应用程序无法在各种环境中保持一致运行(无论是云环境、CI 环境还是生产环境)。作为软件工程师或与工程师密切合作的人,你可能听过那句经典吐槽:“但在我的机器上能跑。”
让应用程序在不同环境中正常运行,长期以来一直是开发者和系统管理员面临的最大挑战之一。工程师们常抱怨:“在我的电脑上没问题。”
我们在本地环境中开发时,可能会发现生产环境中的依赖项与创建应用时使用的略有差异。当试图让两个环境完全一致时,情况变得更加复杂。我们可能还会发现主机上的其他资源依赖某个在另一环境中不存在的依赖项。当环境之间缺乏隔离时,就会陷入这种“依赖地狱”的困境。
容器化通过将应用程序及其所有依赖项封装成一个独立、自包含的单元来解决这一问题,确保该单元可以在任何地方一致运行。
虚拟机与容器的区别
虚拟机和容器都能实现资源隔离,但两者并不相同。
- 虚拟机通过虚拟化硬件实现隔离,而容器则虚拟化操作系统,每个容器包含应用代码和其依赖项。
- 容器通常只有几兆字节大小,因此具有良好的可移植性,便于在不同环境间移动。
- 容器启动迅速,无需像虚拟机那样经历漫长的启动过程。
- 相比虚拟机,容器消耗的资源更少,内存占用更小。
- 在虚拟化中,每个客户机操作系统都需要单独打补丁和更新;而在容器中,只需更新宿主操作系统即可。
使用虚拟机还是容器?
何时使用虚拟机,何时使用容器?答案取决于具体场景。
如果正在开发基于微服务的应用程序,或计划迁移到微服务架构,应选择容器。由于容器体积小、轻量且启动快,非常适合需要在多个环境中快速扩展的微服务或云应用。
容器占用更少的内存和 RAM,使我们能在同一台物理服务器上部署更多应用,高效利用可用资源。当项目强调可移植性、可扩展性和可维护性时,推荐使用容器。
如果需要在一个安全、隔离的沙箱环境中运行应用,并确保不同工作负载之间相互隔离,虚拟机更为合适。它提供了更强的工作负载隔离性和安全性。与共享宿主机内核的容器不同,虚拟机是完全隔离的。
如果应用需要回滚功能,例如能够将数据或系统恢复到某个特定时间点,应选择虚拟机。虚拟机平台支持在特定时间点对虚拟机进行快照,并在必要时恢复。
此外,将容器运行在虚拟机中,可以兼得两者的优点。容器与虚拟机可以共存。
尽管还有其他容器运行时环境,如 Podman、LXC 等,但我们将重点聚焦最主流的运行时——Docker。
Docker
根据上下文,“Docker”一词可能指代多种含义。有必要澄清一些常见误解。
- Docker, Inc:是 Docker 技术背后的公司。
- Docker:指整个 Docker 项目。它是一个供开发者和系统管理员构建、交付和运行应用的平台。
“Docker”有时被当作“Docker, Inc.”的同义词使用。关键在于注意使用语境——它可能指技术本身,也可能指公司。通常情况下,“Docker”指的是技术。
Docker 改变了我们开发、打包和部署应用的方式。虽然将应用打包进容器的概念并非始于 Docker,早在 1979 年的 Unix v7 中就已有进程隔离机制。
Docker 通过提供简洁的本地守护进程和强大的工具链,隐藏了容器化的复杂性,极大简化了系统管理员和开发者的操作。
Docker 还内置了高效的镜像分层机制(稍后详述),以及用于创建和共享 Docker 镜像的注册中心。这也是为什么如今 Docker 已成为几乎所有开发流程中的必备工具。
Docker 架构
Docker 平台采用客户端-服务器架构。这种架构由客户端和服务器组成,客户端向集中式服务器(即宿主机)发起请求并接收服务。在 Docker 的语境中,Docker 守护进程(daemon)扮演服务器角色,Docker CLI 则是客户端。
Docker 守护进程在宿主机后台运行,持续等待处理请求。它是 Docker 容器平台的控制中心,通过 REST API 提供接口供外部交互。这意味着任何人都可以开发一个 Docker 客户端来连接守护进程。不过,除非有特殊需求,一般无需自行开发客户端。建议使用专为此目的设计的 Docker CLI 工具来与守护进程通信。
目前,Docker 守护进程仅在 Linux 上运行,因为它依赖多个 Linux 内核特性来实现环境隔离(后续详解)。但这并不意味着不能在 Mac 或 Windows 上使用 Docker。可以通过其他方式在这些系统上运行 Docker。
例如,可在 Windows 上运行一个 Linux 虚拟机来承载 Docker,并通过客户端访问其 API。由于 Docker 是客户端-服务器架构,服务器的位置与客户端的距离无关。我们可以远程访问和管理。
Docker 容器与 Docker 镜像的区别
随着对 Docker 的深入了解,我们会频繁看到“Docker 容器”和“Docker 镜像”这两个术语。若想深入掌握 Docker,必须清楚区分二者。
Docker 镜像
Docker 镜像 是一个文件,代表打包好的软件代码,包含所有依赖项、运行时环境、配置和库。一旦创建,Docker 镜像便不可更改。每次修改都会生成全新的镜像。镜像的不可变性保证了它在任何环境下都能以相同方式运行。
Docker 镜像可以被分发。Docker 拥有一个名为 Docker Hub 的公共镜像仓库,作为镜像的存储库。由于镜像不可变,我们可以放心发布并分享给他人,确信镜像将持续正常运行。
然而,未运行的镜像价值有限。即使我们分享了一个镜像,真正发挥作用的仍是正在运行的实例。
Docker 容器
Docker 容器 是 Docker 镜像的一个运行实例。如果你熟悉面向对象编程语言,应该对“类”和“实例”的概念很熟悉。如果把 Docker 镜像比作“类”,那么 Docker 容器就是该类的“实例”。
一个 Docker 镜像可以有多个运行实例,就像一个类可以有多个对象一样。也就是说,我们可以用同一个镜像同时启动多个容器。
需要注意的是,不能简单认为 Docker 容器就是正在运行的镜像实例。Docker 容器并不一定处于“运行”状态。容器在 Docker 中有五种状态:已创建、运行中、暂停、已停止 或 已删除。
Docker 容器共有五种可能状态,我们可以使用 Docker CLI 执行创建、启动、重启、暂停等操作。下一章将深入探讨这些操作。
为何以及何时使用 Docker?
打造开发者喜爱并愿意使用的产品,关键在于让他们的工作更轻松。Docker 正是如此:它抽象了复杂性,简化了容器管理,有效缓解了开发者和系统管理员的痛点。
无论软件多么复杂,运行一个 Docker 镜像都只需一条命令。如果不再需要该软件,也可以通过一条命令彻底移除,系统恢复如初。
Docker 节省了时间、精力和成本,让我们能专注于最重要的事——开发软件本身。
几乎每个人都使用 Docker 容器。其生态系统庞大,受到各大科技公司的积极支持。在 2019 年 Stack Overflow 调查中,Docker 是最受欢迎和最渴望拥有的平台。它的流行度不会下降,因为几乎所有科技驱动型公司都在使用 Docker。
既然 Docker 有这么多优势,是否可以用于几乎所有场景?什么时候适合使用 Docker?
Docker 可以运行所有基于 Linux 的应用程序,也能运行在 Windows 服务器上运行的 Windows 应用程序,如数据库、Web 服务器和邮件服务器。但无法运行原生的 Windows 或 macOS 桌面应用程序。这意味着我们无法在 Docker 中运行浏览器、IDE、文字处理器或图形编辑器等常用桌面软件。
总结上述内容,以下是使用 Docker 容器的典型场景:
- 当需要在多个环境(如本地、测试、CI、生产)中运行软件时。
- 当可移植性至关重要,希望共享软件时。
- 当希望加快团队协作效率,让成员在几分钟内快速上手,并确保多环境一致性时。
- 当希望节省成本,或在有限硬件预算下尽可能多地部署应用时。
Quiz
关于虚拟化,以下哪一项说法是正确的?