上一篇 下一篇 分享链接 返回 返回顶部

Docker 和 Kubernetes 有什么区别?从容器打包到集群编排,附配置文件实战

发布人:慈云数据-客服中心 发布时间:8小时前 阅读量:4

Docker 和 Kubernetes 对比|附配置文件

在云原生技术快速发展的今天,DockerKubernetes 几乎是每个后端工程师、运维工程师、架构师都绕不开的两个关键词。很多初学者会把它们放在一起比较,甚至认为 Kubernetes 是 Docker 的替代品。但严格来说,二者并不是同一层面的工具:Docker 更偏向于容器的构建、运行和管理,而 Kubernetes 更偏向于容器集群的编排和调度

本文将从概念、架构、使用场景、核心能力、配置文件示例等多个角度,对 Docker 和 Kubernetes 进行系统对比,并附上常见配置文件示例,帮助你更清晰地理解它们之间的关系和区别。


一、Docker 是什么?

Docker 是一个开源的容器化平台,它可以将应用程序及其运行依赖打包到一个轻量级、可移植的容器中,从而实现“一次构建,到处运行”。

在传统部署方式中,一个应用往往依赖特定版本的操作系统、语言运行时、系统库、环境变量等。如果开发环境、测试环境和生产环境不一致,就很容易出现“在我电脑上明明可以运行”的问题。

Docker 通过镜像和容器解决了这个问题。

Docker 的核心概念

1. 镜像 Image

镜像可以理解为一个只读模板,里面包含应用程序、依赖库、运行环境和启动命令。例如,一个 Java 应用镜像可能包含:

  • JDK
  • Spring Boot 应用 jar 包
  • 配置文件
  • 启动脚本

镜像是容器运行的基础。

2. 容器 Container

容器是镜像运行起来之后的实例。镜像类似“类”,容器类似“对象”。

一个镜像可以启动多个容器,每个容器之间相互隔离,但共享宿主机内核。

3. Dockerfile

Dockerfile 是用于构建镜像的配置文件,它描述了镜像如何一步步生成。

4. Docker Compose

Docker Compose 是 Docker 官方提供的多容器编排工具,适合在单机环境下启动多个服务,例如应用服务、MySQL、Redis、Nginx 等。


二、Kubernetes 是什么?

Kubernetes,简称 K8s,是一个开源的容器编排平台,最初由 Google 设计并开源,目前由 CNCF 维护。

如果说 Docker 解决的是“如何把应用打包成容器并运行”的问题,那么 Kubernetes 解决的是“如何在大规模服务器集群中可靠地运行和管理容器”的问题。

Kubernetes 具备以下能力:

  • 自动调度容器到合适的节点
  • 容器故障后自动重启
  • 节点故障后自动迁移
  • 服务发现和负载均衡
  • 滚动发布和回滚
  • 自动扩缩容
  • 配置和密钥管理
  • 存储编排
  • 集群资源管理

在生产环境中,当服务数量、服务器数量、容器数量逐渐增多时,单纯使用 Docker 命令或 Docker Compose 已经难以管理,这时 Kubernetes 的价值就体现出来了。


三、Docker 和 Kubernetes 的关系

Docker 和 Kubernetes 不是简单的竞争关系,而是上下层关系。

可以这样理解:

  • Docker:负责容器镜像构建和单机容器运行
  • Kubernetes:负责多个节点上的容器调度、编排和管理

在早期 Kubernetes 中,Docker 曾经是最常用的容器运行时。但从 Kubernetes 1.24 开始,Kubernetes 移除了对 dockershim 的内置支持,默认更推荐使用符合 CRI 标准的容器运行时,例如:

  • containerd
  • CRI-O

需要注意的是,这并不意味着 Docker 镜像不能在 Kubernetes 中运行。Docker 构建出来的镜像仍然符合 OCI 镜像标准,可以被 containerd、CRI-O 等运行时正常拉取和运行。

换句话说:

Docker 仍然常用于本地开发和镜像构建,而 Kubernetes 常用于生产环境中的集群编排。


四、Docker 和 Kubernetes 核心区别对比

下面通过表格对二者进行对比。

对比维度 Docker Kubernetes
定位 容器化平台 容器编排平台
主要作用 构建、运行、管理容器 调度、编排、管理容器集群
使用场景 本地开发、单机部署、小规模服务 生产集群、大规模微服务、多节点部署
管理范围 单台主机为主 多台主机组成的集群
配置方式 Dockerfile、docker-compose.yml YAML 资源清单
服务发现 需要借助 Compose 网络或额外工具 内置 Service 和 DNS
负载均衡 基础能力较弱 内置服务负载均衡
自动恢复 容器可配置 restart 策略 Pod 自动重建、节点故障迁移
扩缩容 手动或借助脚本 支持手动和自动扩缩容
滚动发布 需要额外脚本或 Compose 支持有限 原生支持 Deployment 滚动更新
学习成本 较低 较高
适合团队 个人、小团队、开发测试 中大型团队、生产环境

五、Docker 的典型使用场景

Docker 更适合以下场景:

1. 本地开发环境统一

开发团队可以通过 Docker 构建一致的开发环境。例如后端服务依赖 MySQL、Redis、RabbitMQ 等中间件,团队成员无需分别安装,只需执行:

docker compose up -d

即可启动完整开发环境。

2. 应用镜像构建

在 CI/CD 流水线中,Docker 通常用于构建应用镜像。例如:

docker build -t my-app:1.0.0 .

然后将镜像推送到镜像仓库:

docker push registry.example.com/my-app:1.0.0

3. 单机部署

对于一些小型项目、个人项目、内部工具,单机 Docker 部署已经足够。通过 Docker Compose 可以同时管理 Web 服务、数据库、缓存等组件。


六、Kubernetes 的典型使用场景

Kubernetes 更适合以下场景:

1. 微服务架构

当系统拆分为多个微服务后,每个服务可能有多个副本,并且服务之间需要发现和调用。Kubernetes 提供了 Service、DNS、Ingress 等机制,非常适合管理微服务。

2. 高可用生产环境

Kubernetes 可以在 Pod 异常退出后自动重启,也可以在节点故障时将应用调度到其他可用节点上,从而提高系统可用性。

3. 弹性伸缩

在流量高峰时,可以通过 HPA 根据 CPU、内存或自定义指标自动扩容服务副本数;在低峰时自动缩容,节省资源。

4. 标准化交付

Kubernetes 使用声明式 YAML 描述应用状态,适合 GitOps、DevOps 和自动化发布流程。


七、Docker 配置文件示例

下面以一个简单的 Spring Boot 应用为例,展示 Dockerfile 和 Docker Compose 配置。

假设项目结构如下:

my-app/
├── Dockerfile
├── docker-compose.yml
└── target/
    └── my-app.jar

1. Dockerfile 示例

# 使用精简版 JDK 运行环境作为基础镜像
FROM eclipse-temurin:17-jre-alpine

# 设置工作目录
WORKDIR /app

# 复制 jar 包到镜像中
COPY target/my-app.jar app.jar

# 暴露应用端口
EXPOSE 8080

# 设置 JVM 参数,可通过环境变量覆盖
ENV JAVA_OPTS="-Xms256m -Xmx512m"

# 容器启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

这个 Dockerfile 的作用是将 Spring Boot 应用打包成一个可运行镜像。构建命令如下:

docker build -t my-app:1.0.0 .

运行容器:

docker run -d \
  --name my-app \
  -p 8080:8080 \
  my-app:1.0.0

2. docker-compose.yml 示例

如果应用依赖 MySQL 和 Redis,可以使用 Docker Compose 一键启动。

version: "3.9"

services:
  app:
    image: my-app:1.0.0
    container_name: my-app
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      MYSQL_HOST: mysql
      MYSQL_PORT: 3306
      REDIS_HOST: redis
      REDIS_PORT: 6379
    depends_on:
      - mysql
      - redis
    restart: always

  mysql:
    image: mysql:8.0
    container_name: my-mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root123456
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_pass
    volumes:
      - mysql-data:/var/lib/mysql
    restart: always

  redis:
    image: redis:7-alpine
    container_name: my-redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    restart: always

volumes:
  mysql-data:
  redis-data:

启动命令:

docker compose up -d

查看容器:

docker compose ps

停止服务:

docker compose down

Docker Compose 的优点是简单直观,非常适合开发测试和小规模部署。但它主要面向单机环境,在集群调度、高可用、自动扩缩容方面能力有限。


八、Kubernetes 配置文件示例

Kubernetes 使用 YAML 文件描述资源对象。常见资源包括:

  • Deployment:管理应用副本和滚动发布
  • Service:提供稳定访问入口和负载均衡
  • ConfigMap:管理普通配置
  • Secret:管理敏感信息
  • Ingress:管理 HTTP/HTTPS 入口
  • PersistentVolumeClaim:申请持久化存储

下面仍以同一个应用为例。


1. Deployment 配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: registry.example.com/my-app:1.0.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: "prod"
            - name: MYSQL_HOST
              value: "mysql"
            - name: REDIS_HOST
              value: "redis"
          resources:
            requests:
              cpu: "250m"
              memory: "512Mi"
            limits:
              cpu: "500m"
              memory: "1Gi"
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 20
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 40
            periodSeconds: 15

这个 Deployment 表示希望 Kubernetes 始终保持 3 个 my-app 副本运行。如果某个 Pod 异常退出,Kubernetes 会自动创建新的 Pod 来补足副本数。


2. Service 配置

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

Service 为 Pod 提供稳定访问入口。即使后端 Pod 被重建,Service 的名称和虚拟 IP 也保持稳定。在集群内部,其他服务可以通过以下地址访问:

http://my-app-service

3. ConfigMap 配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
data:
  application.yml: |
    server:
      port: 8080

    spring:
      datasource:
        url: jdbc:mysql://mysql:3306/app_db?useSSL=false&serverTimezone=Asia/Shanghai
        username: app_user
      redis:
        host: redis
        port: 6379

ConfigMap 适合存放非敏感配置,例如服务端口、数据库地址、缓存地址等。

如果要在 Deployment 中挂载 ConfigMap,可以这样配置:

volumeMounts:
  - name: config-volume
    mountPath: /app/config
volumes:
  - name: config-volume
    configMap:
      name: my-app-config

4. Secret 配置

敏感信息不建议直接写入 ConfigMap,例如数据库密码、Token、证书等,应该使用 Secret。

apiVersion: v1
kind: Secret
metadata:
  name: my-app-secret
type: Opaque
stringData:
  MYSQL_PASSWORD: app_pass
  JWT_SECRET: my-jwt-secret

在 Deployment 中引用 Secret:

env:
  - name: MYSQL_PASSWORD
    valueFrom:
      secretKeyRef:
        name: my-app-secret
        key: MYSQL_PASSWORD

需要注意,Kubernetes Secret 默认只是 Base64 编码,并不等于强加密。生产环境中还应结合 RBAC、KMS、密钥管理系统等手段提升安全性。


5. Ingress 配置

如果希望从集群外部通过域名访问应用,可以配置 Ingress。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app-service
                port:
                  number: 80

访问方式:

http://app.example.com

Ingress 通常需要配合 Ingress Controller 使用,例如 Nginx Ingress Controller、Traefik、APISIX Ingress 等。


6. HPA 自动扩缩容配置

Kubernetes 可以根据 CPU 使用率自动调整 Pod 副本数。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60

这段配置表示:当 CPU 平均使用率超过 60% 时,Kubernetes 会在 3 到 10 个副本之间自动扩容或缩容。


九、从 Docker Compose 到 Kubernetes 的迁移思路

很多团队一开始会使用 Docker Compose 部署服务,随着业务增长再迁移到 Kubernetes。迁移时可以按照以下思路进行:

1. 拆分服务

Docker Compose 中的每个 service,在 Kubernetes 中通常会拆分成:

  • Deployment
  • Service
  • ConfigMap
  • Secret
  • PVC

例如 Compose 中的 app 服务,在 Kubernetes 中至少需要一个 Deployment 和一个 Service。

2. 处理配置

Compose 中的 environment 可以迁移到 Kubernetes 的 env、ConfigMap 或 Secret 中。

普通配置放 ConfigMap,敏感配置放 Secret。

3. 处理数据持久化

Compose 中的 volume 需要迁移为 Kubernetes 的 PersistentVolumeClaim。

例如 MySQL 的数据目录不应随 Pod 删除而丢失,需要使用持久化存储。

4. 处理服务访问

Compose 中服务之间可以通过 service name 访问。Kubernetes 中服务之间通过 Service 名称访问,例如:

mysql.default.svc.cluster.local

或者简写为:

mysql

5. 处理外部入口

Compose 常通过端口映射暴露服务,例如:

ports:
  - "8080:8080"

Kubernetes 中可以使用:

  • NodePort
  • LoadBalancer
  • Ingress

生产环境中更推荐使用 Ingress 或云厂商 LoadBalancer。


十、Docker 和 Kubernetes 如何选择?

如果你正在做技术选型,可以参考以下建议。

选择 Docker 的情况

如果你的项目满足以下条件,Docker 或 Docker Compose 通常已经足够:

  • 项目规模较小
  • 服务数量较少
  • 只部署在单台服务器上
  • 不需要复杂的自动扩缩容
  • 团队运维能力有限
  • 更重视简单快速上线

例如个人博客、内部管理系统、小型 API 服务、测试环境等,都可以优先使用 Docker Compose。

选择 Kubernetes 的情况

如果你的项目具备以下特点,更适合使用 Kubernetes:

  • 服务数量较多
  • 采用微服务架构
  • 需要多节点部署
  • 对高可用要求较高
  • 需要滚动发布和快速回滚
  • 需要自动扩缩容
  • 团队具备一定运维和平台能力
  • 计划建设统一的 DevOps 或云原生平台

不过,也要注意 Kubernetes 并不是银弹。它的学习成本、维护成本和排障复杂度都明显高于 Docker。对于小团队来说,如果没有专门人员维护集群,贸然上 Kubernetes 可能会增加不必要的负担。


十一、常见误区

误区一:Kubernetes 替代了 Docker

不准确。Kubernetes 替代的不是 Docker 的全部能力,而是部分单机容器管理能力。Docker 仍然可以用于镜像构建、本地开发、调试和简单部署。

误区二:用了 Kubernetes 就一定高可用

不一定。Kubernetes 提供了高可用的基础能力,但应用本身也需要支持无状态化、健康检查、优雅停机、配置外置、数据库高可用等设计。否则只是把不稳定的应用放进了更复杂的平台。

误区三:Docker Compose 不能用于生产

Docker Compose 并非绝对不能用于生产。对于小规模系统,只要做好数据备份、日志收集、监控告警、重启策略和安全配置,Compose 也可以满足需求。但对于复杂生产环境,Kubernetes 的治理能力更强。

误区四:Kubernetes 配置越复杂越专业

Kubernetes YAML 并不是越复杂越好。高质量的配置应该清晰、可维护、可复用,并且符合实际业务需求。过度抽象和过度配置反而会提高维护成本。


十二、总结

Docker 和 Kubernetes 是云原生体系中非常重要的两个工具,但它们解决的问题不同。

Docker 的核心价值在于容器化
它让应用和依赖可以被统一打包、快速分发、稳定运行,非常适合本地开发、镜像构建和单机部署。

Kubernetes 的核心价值在于容器编排
它让大量容器可以在集群中被自动调度、弹性伸缩、故障恢复和统一管理,非常适合生产环境和微服务架构。

简单来说:

Docker 解决“如何把应用装进容器并运行”的问题;
Kubernetes 解决“如何在集群中稳定、高效地管理大量容器”的问题。

在实际项目中,二者往往是配合使用的:开发阶段用 Docker 构建镜像和本地调试,生产阶段将镜像部署到 Kubernetes 集群中,由 Kubernetes 负责服务治理、扩缩容和高可用管理。

如果你是初学者,建议先掌握 Docker 的基础概念和 Docker Compose 的使用,再逐步学习 Kubernetes 的核心资源对象,如 Pod、Deployment、Service、ConfigMap、Secret、Ingress 和 HPA。这样学习路径会更自然,也更容易理解云原生应用的完整交付流程。

目录结构
全文