☰
Docker、Docker Compose 与 Kubernetes:分别解决什么问题?
2026/10/31 18:17:02 网站建设 项目流程

刚接触容器技术时,Docker、Docker Compose 和 Kubernetes 经常一起出现,很容易让人误以为它们是三种差不多的工具。其实,它们解决的问题处在不同层次:

  • Docker 负责把一个应用装进容器,并运行起来。
  • Docker Compose 负责在一台机器上组织多个容器。
  • Kubernetes 负责在多台机器上管理大量容器,并让系统持续稳定运行。

可以先记住一句简单的话:

Docker 管一个容器,Docker Compose 管一组容器,Kubernetes 管一个容器集群。

一、为什么需要 Docker?

假设你开发了一个 Java 网站,在自己的电脑上运行正常。交给同事或部署到服务器后,却出现了各种问题:

  • 服务器没有安装 Java。
  • Java 版本不一致。
  • 缺少某些系统依赖。
  • 配置文件路径不同。
  • 同事不知道该执行哪些启动命令。

这就是开发中常见的“在我电脑上明明能运行”。Docker 的做法是:把应用程序、运行环境、依赖和启动命令一起打包成镜像。Docker 官方将镜像描述为运行容器所需文件、程序库和配置的标准化软件包。拿日常外卖举个例子:

  • 应用代码是食物。
  • Java、Node.js 等运行环境是餐具。
  • 配置和依赖是调料。
  • Docker 镜像是封装好的外卖套餐。
  • 容器是这份套餐真正被打开并使用的状态。

同一个镜像可以启动多个容器,就像同一份套餐模板可以制作出很多份外卖。

1、镜像和容器有什么区别?

镜像是一份只读模板,容器是镜像运行后的实例。可以把它们理解为:

镜像 = 程序安装包
容器 = 已经启动的程序

例如,通过下面的命令启动一个 Nginx 容器:

docker run -d -p 8080:80 --name my-nginx nginx

这条命令做了几件事:

  1. 获取nginx镜像。
  2. 根据镜像创建一个名为my-nginx的容器。
  3. 在后台运行容器。
  4. 把本机的 8080 端口映射到容器的 80 端口。

访问http://localhost:8080,就能看到 Nginx 页面。

2、Dockerfile 是什么?

如果要把自己的应用制作成镜像,通常需要编写 Dockerfile。下面是一个简单的 Java 应用示例:

FROM eclipse-temurin:17-jre

WORKDIR /app

COPY target/demo.jar app.jar

EXPOSE 8080

CMD ["java", "-jar", "app.jar"]

它表达的意思很直接:

  • 使用带有 Java 17 的基础镜像。
  • 把工作目录设为/app。
  • 将项目生成的 JAR 文件复制进去。
  • 声明应用使用 8080 端口。
  • 容器启动时执行java -jar app.jar。

然后构建并运行:

docker build -t demo-app:1.0 . docker run -d -p 8080:8080 demo-app:1.0

这样,其他人不需要手动安装 Java,也不必研究项目的启动方式。只要能运行容器,就能按照同样的方式启动这个应用。

二、为什么还需要 Docker Compose?

只有一个容器时,使用docker run并不麻烦。实际项目通常不止一个服务。例如,一个普通网站可能包含:

前端 Nginx
↓
Java 后端
↓
MySQL 数据库
↓
Redis 缓存

如果全部使用docker run,需要分别配置端口、网络、环境变量和数据卷。启动命令会越来越长,而且很容易漏掉参数。Docker Compose 就是用来处理这种情况的。它允许我们在一个 YAML 文件中定义多个服务、网络和数据卷,再通过一条命令统一启动。Docker 官方把 Compose 定义为“用于定义和运行多容器应用的工具”。

举一个简单示例:下面的compose.yaml定义了一个 Java 应用和一个 MySQL 数据库:

services: app: build: . ports: - "8080:8080" environment: DB_HOST: mysql DB_PORT: 3306 DB_NAME: demo DB_USER: root DB_PASSWORD: "123456" depends_on: - mysql mysql: image: mysql:8.4 environment: MYSQL_ROOT_PASSWORD: "123456" MYSQL_DATABASE: demo volumes: - mysql-data:/var/lib/mysql volumes: mysql-data:

在这个文件所在目录执行:

docker compose up -d

Compose 会完成这些工作:

  • 构建并启动 Java 应用。
  • 下载并启动 MySQL 镜像。
  • 建立容器之间的网络。
  • 创建数据库存储卷。
  • 把后端服务的 8080 端口暴露给本机。

查看日志可以执行:

docker compose logs -f

停止并删除这些容器:

docker compose down docker compose down -v //-v 会删除数据库使用的数据卷,已有数据可能随之消失。

注:早期版本使用带连字符的独立命令:docker-compose up -d,现在主流版本已经把 Compose 集成进 Docker CLI,通常使用:docker compose up -d,两者只是写法不同罢了。

三、为什么又出现了 Kubernetes?

Docker Compose 很适合开发、测试和单机部署。不过,当系统运行在多台服务器上时,事情会迅速变复杂。

假设一个电商网站原来只有一个后端容器。促销开始后,访问量突然增加,需要运行十个后端实例。此时会遇到一连串问题:

  • 十个容器应该分配到哪些服务器?
  • 某台服务器宕机后,容器怎么办?
  • 某个容器崩溃后,谁负责重启?
  • 用户请求怎样分发到不同容器?
  • 发布新版本时,怎样避免整个网站停机?
  • 访问量下降后,怎样减少实例,节省资源?

这些事情靠人工处理并不现实。Kubernetes,简称 K8s,就是用来自动管理容器化应用的。Kubernetes 是一个用于管理容器化工作负载和服务的平台,支持声明式配置和自动化。

四、理解 Kubernetes 的几个基本概念

Kubernetes 的概念很多,入门时先抓住 Node、Pod、Deployment 和 Service 就够了。

1、Node:运行容器的机器

Node 是 Kubernetes 集群中的工作机器,可以是物理服务器,也可以是云服务器或虚拟机。举个例子:

Kubernetes 集群
├── Node 1:192.168.1.11
├── Node 2:192.168.1.12
└── Node 3:192.168.1.13

Kubernetes 会把应用分配到这些 Node 上运行。一个标准集群由控制平面和一台或多台工作节点组成。

2、Pod:Kubernetes 中最小的部署单位

Kubernetes 通常不直接管理单个容器,而是管理 Pod。一个 Pod 可以包含一个或多个关系非常紧密的容器。大多数业务场景中,一个 Pod 里只有一个主要应用容器。

Pod
└── Java 应用容器

Pod
├── Java 应用容器
└── ELK日志采集容器

同一个 Pod 内的容器共享网络环境,也可以共享存储。可以暂时把 Pod 理解为“给容器套了一层 Kubernetes 管理外壳”。

3、Deployment:管理 Pod 的数量和版本

如果我们希望运行三个 Java 应用实例,可以定义一个 Deployment:

apiVersion: apps/v1 kind: Deployment metadata: name: demo-app spec: replicas: 3 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: demo-app image: example/demo-app:1.0 ports: - containerPort: 8080

其中,replicas: 3表示期望运行三个 Pod。Kubernetes 会不断检查实际状态,如果其中一个 Pod 崩溃,Deployment 会重新创建一个。Kubernetes 关心的不是某个具体 Pod 必须永远活着,而是系统要始终保持三个可用副本。

4、Service:给 Pod 提供稳定入口

Pod 可能随时被销毁和重建,IP 地址也可能变化。客户端不能把请求直接绑定到某个 Pod 的 IP。Service 会在一组 Pod 前面提供一个稳定的访问入口:

用户请求
↓
Service
↙ ↓ ↘
Pod Pod Pod

即使后面的 Pod 被替换,Service 的访问方式仍然可以保持不变。它还能把请求分发给多个 Pod。Kubernetes 官方将 Service 描述为向一个或多个 Pod 暴露网络应用的方法。对应的参考配置:

apiVersion: v1 kind: Service metadata: name: demo-app-service spec: selector: app: demo-app ports: - port: 80 targetPort: 8080 type: ClusterIP

这里的选择器selector:app:demo-app会找到带有相同标签的 Pod。

五、三者之间到底是什么关系?

接下来我们用个餐厅做比喻:

1、Docker:负责标准化每一道菜。Docker 规定菜怎么做、需要哪些原料、做好后装进什么盒子。同一个镜像在不同机器上运行,环境差异会小很多。

2、Docker Compose:负责一桌套餐。一个网站不只有后端,还需要数据库和缓存。Compose 把这些服务写进同一份菜单:

一份套餐
├── 前端
├── 后端
├── MySQL
└── Redis

执行一条命令,整套服务一起启动。它通常管理的是一台主机上的多个容器。

3、Kubernetes:负责经营连锁餐厅。当应用分布在多台服务器上,Kubernetes 开始发挥作用:

  • 哪台服务器有空闲资源,就把 Pod 调度过去。
  • 某个实例坏了,就创建新的。
  • 顾客变多时,可以增加应用副本。
  • 发布新版本时,可以逐批替换旧版本。
  • 对外提供统一入口,把请求分给不同实例。

因此,三者不是简单的替代关系,而是层次不同:

应用代码
↓
Dockerfile 构建镜像
↓
Docker 运行容器
↓
Docker Compose 组织单机上的多个容器
↓
Kubernetes 编排集群中的容器化应用

六、写在最后

三者的定位可以简化为下面这张表:

工具主要用途常见使用场景
Docker构建镜像、运行容器打包和运行单个应用
Docker Compose定义并启动多个关联容器本地开发、测试、单机部署
Kubernetes在集群中调度和管理容器化应用多机部署、扩容、故障恢复、滚动更新

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询