Docker, Compose 与 K8s
Published in:2025-12-11 |
Words: 3.6k | Reading time: 15min | reading:

从零构建微服务架构:Docker, Compose 与 K8s 的演进之路

在现代云原生开发的浪潮中,微服务(Microservices) 已经成为构建复杂系统的首选架构。然而,随着服务数量的裂变,如何开发、打包、部署和管理这些服务成为了巨大的挑战。

这就引出了我们的三个主角:DockerDocker ComposeKubernetes (K8s)

0、微服务

  • 总体架构与组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
graph TD
%% 定义样式
classDef client fill:#f9f,stroke:#333,stroke-width:2px;
classDef gateway fill:#ff9,stroke:#333,stroke-width:2px;
classDef service fill:#9f9,stroke:#333,stroke-width:2px;
classDef infra fill:#9cf,stroke:#333,stroke-width:2px;
classDef db fill:#ffcc00,stroke:#333,stroke-width:2px;

%% 外部访问层
subgraph Client_Layer [客户端层]
Web[Web浏览器]:::client
App[移动端App]:::client
IoT[物联网设备]:::client
end

%% 网关层 (入口)
subgraph Gateway_Layer [API 网关层]
Gateway[API Gateway<br>(Nginx / Spring Cloud Gateway)]:::gateway
note1[功能: 路由转发, 鉴权, 限流]
end

%% 微服务集群 (业务逻辑)
subgraph Service_Cluster [微服务业务集群]
direction TB

subgraph Svc_A [订单服务集群]
ServiceA1[订单服务 实例1]:::service
ServiceA2[订单服务 实例2]:::service
end

subgraph Svc_B [用户服务集群]
ServiceB1[用户服务 实例1]:::service
ServiceB2[用户服务 实例2]:::service
end

subgraph Svc_C [库存服务集群]
ServiceC1[库存服务 实例1]:::service
end
end

%% 基础设施与治理层 (框架核心)
subgraph Infra_Layer [微服务治理/基础设施层]
Registry[注册中心<br>(Nacos/Consul/Eureka)]:::infra
Config[配置中心<br>(Nacos/Apollo)]:::infra
Breaker[熔断/限流监控<br>(Sentinel/Hystrix)]:::infra
Tracing[链路追踪<br>(SkyWalking/Zipkin)]:::infra
Log[日志收集<br>(ELK/EFK)]:::infra
end

%% 数据持久层
subgraph Data_Layer [数据层]
MySQL[(主数据库)]:::db
Redis[(缓存 Redis)]:::db
MQ[消息队列 RabbitMQ/Kafka]:::db
end

%% --- 连线关系 ---

%% 1. 客户端访问网关
Web --> Gateway
App --> Gateway
IoT --> Gateway

%% 2. 网关与基础设施交互
Gateway -.->|拉取路由表| Registry
Gateway -.->|拉取配置| Config

%% 3. 网关转发请求到服务
Gateway -->|负载均衡 LB| ServiceA1
Gateway -->|负载均衡 LB| ServiceA2

%% 4. 服务注册与发现
ServiceA1 -.->|注册/心跳| Registry
ServiceB1 -.->|注册/心跳| Registry
ServiceC1 -.->|注册/心跳| Registry

%% 5. 服务间调用 (RPC/Feign)
ServiceA1 -->|RPC调用: 查询用户信息| ServiceB1
ServiceA1 -->|RPC调用: 扣减库存| ServiceC1

%% 6. 异步解耦
ServiceA1 -.->|发送消息| MQ
MQ -.->|消费消息| ServiceC1

%% 7. 基础设施监控
ServiceA1 -.->|上报Metrics| Breaker
ServiceA1 -.->|上报Trace| Tracing

%% 8. 数据访问
ServiceB1 --> MySQL
ServiceC1 --> Redis

  • 微服务间调用详细流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
sequenceDiagram
participant User as 用户
participant Gateway as API网关
participant SvcA as 服务A (消费者)
participant Registry as 注册中心 (Nacos)
participant SvcB as 服务B (提供者)
participant Breaker as 熔断器 (Sentinel)

Note over User, Gateway: 1. 发起请求
User->>Gateway: GET /api/order/create

Note over Gateway, SvcA: 2. 路由转发
Gateway->>SvcA: 转发请求到服务A

Note over SvcA, Registry: 3. 服务发现 (Where are you?)
SvcA->>Registry: 询问: "服务B 的IP列表是什么?"
Registry-->>SvcA: 返回: [192.168.0.1, 192.168.0.2]

Note over SvcA, SvcA: 4. 负载均衡 (Client-Side LB)
SvcA->>SvcA: 算法选择实例 (例如: 轮询选了 192.168.0.2)

Note over SvcA, Breaker: 5. 熔断/限流检查
SvcA->>Breaker: 检查服务B是否健康? 允许调用?

alt 熔断器开启 (服务B挂了)
Breaker-->>SvcA: 拒绝调用 (Block)
SvcA-->>User: 返回降级数据 (比如: "系统繁忙")
else 熔断器关闭 (正常)
Breaker-->>SvcA: 允许通过

Note over SvcA, SvcB: 6. 发起RPC网络调用 (Feign/Dubbo)
SvcA->>SvcB: HTTP/TCP 请求
SvcB-->>SvcA: 返回业务数据 JSON

SvcA-->>User: 返回最终结果
end

文字解析:微服务框架的构成要素

一个完整的微服务架构通常由以下 6 大核心组件 构成:

1. API 网关 (API Gateway)

  • 作用:系统的“门卫”。所有外部请求必须先经过它。
  • 核心功能:统一接入、路由转发(把 /user 转给用户服务)、鉴权(登录检查)、限流(防刷)。
  • 常用技术:Spring Cloud Gateway, Nginx, Kong, APISIX。

2. 注册中心 (Service Registry)

  • 作用:系统的“通讯录”。
  • 核心功能:服务启动时把自己的 IP 登记上去(注册);服务调用时去查对方的 IP(发现)。
  • 常用技术:Nacos, Consul, Eureka, Zookeeper, Kubernetes CoreDNS。

3. 配置中心 (Config Center)

  • 作用:系统的“设置面板”。
  • 核心功能:统一管理所有服务的配置文件(如数据库密码、开关配置),支持热更新(改配置不用重启服务)。
  • 常用技术:Nacos, Apollo, Spring Cloud Config。

4. 远程调用 (RPC / HTTP Client)

  • 作用:服务之间的“电话线”。
  • 核心功能:让服务 A 像调用本地函数一样调用服务 B。
  • 常用技术
    • HTTP: OpenFeign (Spring Cloud), RestTemplate.
    • RPC: Dubbo, gRPC.

5. 负载均衡 (Load Balancing)

  • 作用:系统的“调度员”。
  • 核心功能:当服务 B 有 10 个实例时,服务 A 该调哪一个?负责把流量分摊开。
  • 常用技术:Ribbon, Spring Cloud LoadBalancer, Kubernetes Service.

6. 熔断与限流 (Circuit Breaker & Rate Limiter)

  • 作用:系统的“保险丝”。
  • 核心功能
    • 熔断:当服务 B 挂了,服务 A 自动切断对 B 的调用,防止把自己拖死(雪崩效应)。
    • 降级:调用失败后,返回一个兜底的默认值。
  • 常用技术:Sentinel (阿里), Hystrix (Netflix, 已停更), Resilience4j.

7. 辅助体系 (Observability)

  • 链路追踪:SkyWalking, Zipkin(看请求在哪一步慢了)。
  • 日志系统:ELK Stack(集中看日志)。
  • 监控告警:Prometheus + Grafana(看 CPU、内存水位)。

一、 核心概念与关系图谱

在深入代码之前,我们先用一个通俗的类比来理清它们的关系:

  1. 微服务 (Microservices)

    • 角色:这是**“灵魂”**。
    • 定义:一种架构风格,将单体应用拆分为一组小型服务,每个服务运行在自己的进程中,通过轻量级机制(通常是 HTTP API)通信。
    • 痛点:服务多了,环境配置极其复杂(Python 环境、Java 环境、Node 环境混在一起)。
  2. Docker

    • 角色:这是**“集装箱”**(单兵装备)。
    • 定义:将代码及其依赖(库、环境变量、配置文件)打包成一个标准的镜像(Image)。
    • 解决的问题:解决了“在我的机器上能跑,在服务器上跑不起来”的环境一致性问题。
  3. Docker Compose

    • 角色:这是**“排练场”**(单机编排)。
    • 定义:一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件配置应用的所有服务。
    • 解决的问题:一个微服务系统往往包含 Web 服务、数据库、缓存等。手动敲十几个 docker run 命令太累了,Compose 让你一键启动所有关联服务。主要用于开发环境和测试环境。
  4. Kubernetes (K8s)

    • 角色:这是**“总指挥官”**(集群编排)。
    • 定义:一个开源的容器编排引擎,用于自动化部署、扩展和管理容器化应用程序。
    • 解决的问题:当你的服务需要在几十台服务器上运行,需要自动扩缩容(流量大了加实例)、故障自愈(挂了自动重启)、负载均衡时,Docker Compose 就搞不定了,这时必须上 K8s。主要用于生产环境。

总结关系:

微服务是架构思想 -> Docker 是标准交付单元 -> Compose 是单机组装工具 -> K8s 是跨主机的集群管理平台。


二、 实战演练:从代码到集群

为了演示,我们假设构建一个简单的微服务:一个基于 Python Flask 的 Web 应用,它连接 Redis 数据库来记录访问次数。

第一阶段:Docker 化 (标准化打包)

首先,我们需要编写代码并将其封装进 Docker 容器。

1. 应用代码 (app.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask
import redis

app = Flask(__name__)
# 注意:这里的 host 写的是 'redis',这是服务发现的关键
cache = redis.Redis(host='redis', port=6379)

@app.route('/')
def hello():
count = cache.incr('hits')
return f'Hello World! I have been seen {count} times.\n'

if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)

2. 编写 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 5000

# 启动命令
CMD ["python", "app.py"]

操作:
此时,你可以通过 docker build -t my-web-app . 构建镜像。但你没法直接运行它,因为它依赖 Redis,而你还没启动 Redis。


第二阶段:使用 Docker Compose (本地开发)

在开发阶段,我们需要同时启动 Web 应用和 Redis。

编写 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3.8'
services:
# 服务1: 我们自己的 Web 应用
web:
build: . # 使用当前目录的 Dockerfile 构建
ports:
- "5000:5000"
depends_on:
- redis # 依赖 redis 服务启动

# 服务2: Redis 数据库
redis:
image: "redis:alpine" # 直接使用官方镜像

操作:
只需执行一条命令:

1
docker-compose up -d

Docker 会自动构建镜像、拉取 Redis、创建虚拟网络、启动容器。你的代码中 host='redis' 之所以能通,是因为 Compose 提供了 DNS 解析,将 redis 域名解析到了对应的容器 IP。


第三阶段:迁移至 Kubernetes (生产部署)

到了生产环境,我们需要高可用和扩缩容。Docker Compose 的 YAML 文件不能直接在 K8s 上用,我们需要将其“翻译”成 K8s 的资源对象:DeploymentService

前提:你需要先把镜像推送到仓库,例如 docker push myuser/my-web-app:v1

1. 部署 Redis (redis-k8s.yaml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# --- Redis Deployment (负责管理 Pod) ---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deploy
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379

---
# --- Redis Service (负责内部网络发现) ---
apiVersion: v1
kind: Service
metadata:
name: redis # 代码里的 host='redis' 就是找这个名字
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379

2. 部署 Web 应用 (web-k8s.yaml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# --- Web App Deployment ---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
spec:
replicas: 3 # 生产环境我们要 3 个副本实现负载均衡
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: myuser/my-web-app:v1 # 必须是远程仓库地址
ports:
- containerPort: 5000
env: # 可以在这里注入环境变量
- name: FLASK_ENV
value: "production"

---
# --- Web App Service (对外暴露) ---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
type: LoadBalancer # 或者 NodePort,让外部能访问
ports:
- protocol: TCP
port: 80 # 外部访问端口
targetPort: 5000 # 容器内部端口

操作:

1
2
kubectl apply -f redis-k8s.yaml
kubectl apply -f web-k8s.yaml

三、 技术细节与差异总结

特性 Docker Compose Kubernetes (K8s)
适用场景 本地开发、测试环境、单机部署 大规模生产环境、多机集群
扩缩容 手动 (docker-compose scale) 自动 (HPA)、手动 (kubectl scale)
故障恢复 容器挂了尝试重启(仅限本机) Pod 挂了在任意健康节点重建(漂移)
网络 单机虚拟网桥 复杂的 Overlay 网络 (Flannel/Calico)
配置复杂度 低 (一个 YAML 文件) 高 (需编写 Deployment, Service, Ingress 等)
服务发现 基于容器名的 DNS 基于 CoreDNS 和 Service VIP

四、 常用命令

这是一份为您整理的 Docker、Docker Compose 和 Kubernetes (K8s) 常用高频命令速查表。

为了方便记忆,我将它们按照生命周期(构建、运行、调试、清理)进行了分类。


1. Docker (单兵作战)

适用于操作单个镜像或容器。

场景 命令 说明
构建 docker build -t <镜像名>:<标签> . 使用当前目录的 Dockerfile 构建镜像
运行 docker run -d -p 80:8080 <镜像名> 后台运行,并将宿主机80端口映射到容器8080
查看 docker ps 查看正在运行的容器
docker images 查看本地所有镜像
调试 docker logs -f <容器ID> 实时查看容器日志 (排错必备)
docker exec -it <容器ID> /bin/bash 进入容器内部终端 (就像 SSH 进去一样)
停止 docker stop <容器ID> 停止容器
清理 docker rm <容器ID> 删除容器 (需先停止)
docker rmi <镜像ID> 删除镜像
docker system prune 大杀器:一键清理所有未使用的容器、网络和悬空镜像

2. Docker Compose (小队演练)

适用于本地开发,同时管理 Web、数据库、缓存等多个容器。

场景 命令 说明
启动 docker-compose up -d 最常用:构建并后台启动所有服务
docker-compose up -d --build 代码修改后,强制重新构建并启动
停止 docker-compose down 停止并删除所有容器和网络 (数据卷默认保留)
docker-compose stop 仅停止容器,不删除
查看 docker-compose ps 查看当前编排的所有服务状态
日志 docker-compose logs -f 聚合查看所有服务的日志
docker-compose logs -f <服务名> 只看某个服务 (如 redis) 的日志
重启 docker-compose restart <服务名> 重启指定服务

3. Kubernetes / kubectl (集团军指挥)

适用于生产环境集群管理。

场景 命令 说明
部署/更新 kubectl apply -f <文件名>.yaml 最核心:根据 YAML 文件创建或更新资源
kubectl apply -f <文件夹>/ 批量应用文件夹下所有 YAML
查看状态 kubectl get pods 查看 Pod 运行状态 (Running/Error/CrashLoopBackOff)
kubectl get svc 查看 Service (IP 和端口)
kubectl get deploy 查看 Deployment (副本数)
kubectl get all 查看所有资源
排错(关键) kubectl describe pod <Pod名称> 查报错详情:看为什么起不来 (如镜像拉取失败、资源不足)
kubectl logs -f <Pod名称> 看业务日志 (程序 print 的内容)
kubectl exec -it <Pod名称> -- /bin/bash 进入 Pod 内部
删除 kubectl delete -f <文件名>.yaml 根据配置文件删除资源
kubectl delete pod <Pod名称> 删除单个 Pod (K8s 会自动重启一个新的)

💡 记忆口诀:横向对比

动作 Docker Docker Compose Kubernetes (kubectl)
启动/应用 run up apply
停止/删除 rm down delete
看日志 logs logs logs
进终端 exec exec exec
看列表 ps ps get pods

总结建议:

  1. 开发阶段:死磕 docker-compose up -ddocker build
  2. 运维阶段:死磕 kubectl applykubectl get podskubectl describe

五、 结语

从 Docker 到 Docker Compose,再到 Kubernetes,这是一条**从“独立个体”到“有组织群体”**的进化之路。

  • 如果你是刚开始写微服务,请先精通 DockerDockerfile
  • 如果你需要快速搭建开发环境,Docker Compose 是你的好帮手。
  • 如果你的业务开始爆发,需要管理成百上千个容器,Kubernetes 则是你必须征服的高地。

掌握这套技术栈,你就拥有了构建现代化、高可用后端架构的核心能力。

Prev:
从 PyTorch 训练到 C++ 边缘部署全流程解析
Next:
基于 FastAPI + LangChain 的高并发 Agent 架构解析