闲谈 - 我如何看待 Docker

💡 原文中文,约1800字,阅读约需5分钟。
📝

内容提要

Docker是提供隔离环境的守护程序,核心在于隔离,可解决多服务端口冲突和资源分配问题。它适合状态由外部输入的程序(如Web后端),而数据库等自赋状态程序需谨慎使用。容器内PID=1进程异常会导致容器异常,因此不适合自动退出的程序。其代价是CPU、内存和磁盘IO性能损失。

🔎

延伸解读

Docker 版本兼容性:并非完全“一次构建,到处运行”

文章指出 Docker 官方宣传的“构建一次,到处运行”需要解读。用 Docker 23.x 构建的镜像在 19.x 上可能异常,类似 Java 高版本 Class 文件无法在低版本 JVM 运行。但低版本构建的镜像通常可通过迁移流程在高版本运行,这与 JDK 不同。因此,跨版本使用镜像时需留意构建与运行环境的版本差异。

状态来源决定容器化适用性

作者根据实践经验提出,状态非自赋予的程序适合 Docker,如 Web 后端、PHP CMS;状态自赋予的程序如数据库则需谨慎。因为数据库状态由自身写入文件,容器异常可能导致数据丢失。而由外部输入状态的程序无需担心此问题。这一区分有助于判断哪些服务适合容器化。

PID=1 进程:容器健康判断的关键

容器内也有 PID=1 的守护程序,Docker 通过它是否异常来判定整个容器状态。若该进程退出或异常,容器即被视为异常。因此,Docker 不适合运行一段时间后自动退出的程序。理解这一点,能帮助排查容器无法启动或异常退出的原因。

隔离的收益与性能代价

Docker 的核心是隔离,包括进程、网络和文件系统隔离,解决了多服务端口冲突和资源分配问题,并支持容器集群。但代价是 CPU 性能损失、额外内存占用(因 libc 不共享)以及磁盘 IO 性能损失。在享受隔离便利时,需权衡这些性能开销。

❓

Q&A

Docker 到底是什么?

Docker 是一个具有一套隔离环境的守护程序,也可以说是一种容器化平台,通过提供隔离环境,使应用程序能够在独立的容器中运行。

Docker 的“构建一次,到处运行”真的完全可靠吗?

并不完全可靠。官方宣传“构建一次,到处运行”,但这句话需要解读。例如用 Docker 23.x 构建的镜像在 Docker 19.x 上可能会出现异常,类似 Java 高版本 Class 文件无法在低版本 JVM 运行。不过低版本 Docker 构建的镜像通常可以通过迁移流程正常运行。

哪些类型的程序适合用 Docker 运行?

状态非自赋予的程序适合使用 Docker,比如常见的 Web 后端、PHP CMS 等。而状态自赋予的程序(如数据库)需要谨慎使用,因为容器异常时自赋予并写入文件的状态可能丢失。

为什么 Docker 不适合运行会自动退出的程序?

因为容器内 PID=1 的进程如果异常退出,Docker 就会判定整个容器异常。Docker 作为守护程序,只能通过 PID=1 进程是否持续运行来判断容器状态,所以不适合运行一段时间后自动退出的程序。

Docker 主要解决了哪些问题?

Docker 的核心是隔离,通过进程隔离、网络隔离和文件系统隔离,解决了多个相同服务端口冲突、计算资源分配等问题。例如多个 Node.js 服务可以共享相同端口,通过“容器名+端口”访问,还能用 Dockerfile 和 docker-compose 实现单机容器编排。

使用 Docker 会带来哪些性能代价?

使用 Docker 会带来一点点的 CPU 性能损失、额外的内存占用(因为 libc 不和宿主机共享,需要加载到容器),以及磁盘 IO 性能损失。

🏷️

标签

➡️

继续阅读