Docker Compose 是 Docker 官方的单机多容器编排工具,通过一个 docker-compose.yml 文件定义整个应用栈(前端 + 后端 + 数据库 + 缓存等),一条命令启动全部服务。它是开发环境和中小规模部署的首选方案。
一、核心概念
1.1 三个核心文件
| 文件 | 用途 |
|---|---|
docker-compose.yml | 主配置文件,定义服务、网络、Volume |
.env | 环境变量文件,Compose 自动读取 |
Dockerfile | 单个服务的镜像构建定义(可选,可用现成镜像) |
理解这三个文件的协作关系是使用 Compose 的第一步。docker-compose.yml 负责声明式地描述整个应用的拓扑结构,Dockerfile 定义如何从源码构建出单个容器镜像,而 .env 文件则负责将环境相关的敏感信息(如密码、API 密钥、端口映射)从代码仓库中解耦出来,确保配置在不同环境间灵活切换的同时避免密钥泄露。
1.2 docker-compose.yml 结构
version: '3.8'
services: # 定义各个服务(容器)
web:
build: ./web # 或 image: nginx
ports:
- "3000:3000"
depends_on:
- db
- redis
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes: # 命名卷定义
postgres_data:
redis_data:
networks: # 自定义网络(可选,Compose 自动创建默认网络)
default:
driver: bridge
在上述结构中,services 是最核心的顶级字段,每个服务对应一个运行中的容器或容器组。volumes 用于声明持久化存储,数据可以在容器重启甚至重新创建后依然保留。networks 定义了服务之间的通信网络,Compose 默认会为每个项目创建一个隔离的 Bridge 网络,使得同一项目内的服务可以通过服务名互相解析。值得注意的是,depends_on 只能控制启动顺序,它不会等到被依赖服务真正健康可用后才继续,因此需要配合健康检查配置才能实现可靠的启动时序。
二、常用命令
docker-compose up -d # 后台启动所有服务
docker-compose up --build # 强制重新构建镜像
docker-compose down # 停止并删除容器和网络
docker-compose down -v # 同时删除 Volume
docker-compose ps # 查看运行状态
docker-compose logs -f web # 实时查看 web 服务日志
docker-compose exec db psql -U postgres # 进入容器执行命令
docker-compose restart # 重启所有服务
docker-compose config # 验证并显示完整配置
docker-compose pull # 拉取所有服务的最新镜像
docker-compose images # 列出项目使用的镜像
docker-compose top # 查看容器内进程
docker-compose pause # 暂停服务(不释放资源)
docker-compose unpause # 恢复暂停的服务
docker-compose rm # 删除已停止的容器
docker-compose start # 启动已存在但停止的容器
docker-compose stop # 停止运行中的容器(保留容器)
在实际开发中,docker-compose up -d 是最常用的启动命令,它会自动检测 docker-compose.yml 和 docker-compose.override.yml 的变更。建议养成在每次修改配置文件后运行 docker-compose config 的习惯,这一步可以验证 YAML 语法是否正确、变量替换是否按预期执行以及是否有配置冲突。在排查故障时,docker-compose logs -f --tail=200 <service> 能够快速定位最近发生的异常日志。如果需要进入容器交互式调试,docker-compose exec <service> /bin/sh 是首选方式,它比 docker-compose run 更轻量,因为前者在现有容器中执行命令,后者则会创建临时新容器。生产环境中还应该注意 docker-compose pull 的作用,在部署前拉取更新后的镜像版本,避免因本地缓存导致部署了旧版本代码。
三、全栈示例:Next.js + Postgres + Redis
# docker-compose.yml
version: '3.8'
services:
# Next.js 前端应用
app:
build:
context: ./app
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
- db
- redis
volumes:
- ./app:/app # 开发模式:代码热重载
- /app/node_modules # 排除 node_modules(容器内版本)
# PostgreSQL 数据库
db:
image: postgres:15-alpine
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: myapp
# Redis 缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
# 启动
cp .env.example .env # 创建环境变量文件
docker-compose up -d
# 执行数据库迁移
docker-compose exec app npx prisma migrate deploy
# 查看日志
docker-compose logs -f app
这个全栈示例覆盖了现代 Web 开发中最常见的三层架构:前端应用层、数据持久层和高速缓存层。在开发模式下,通过将本地源代码目录挂载到容器中,可以实现代码修改后即时生效,无需手动重建容器。node_modules 的匿名卷声明非常关键,它能防止宿主机上的 node_modules(可能与容器内的操作系统架构不匹配)覆盖容器内已安装好的依赖。生产环境中则应移除开发用的 volumes 挂载,改为使用构建好的镜像直接运行。此外建议为 db 服务添加 restart: unless-stopped 策略,这样即使宿主机意外重启,数据库服务也能自动恢复运行,避免数据服务长时间不可用。
四、多环境配置
# docker-compose.yml(基础配置)
version: '3.8'
services:
app:
build: ./app
ports:
- "3000:3000"
environment:
NODE_ENV: ${NODE_ENV}
networks:
- backend
db:
image: postgres:15-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: myapp
networks:
- backend
networks:
backend:
driver: bridge
volumes:
postgres_data:
# docker-compose.override.yml(开发环境,自动加载)
version: '3.8'
services:
app:
volumes:
- ./app:/app
- /app/node_modules
environment:
DEBUG: "true"
LOG_LEVEL: "debug"
command: ["npm", "run", "dev"]
db:
ports:
- "5432:5432"
environment:
POSTGRES_LOG_STATEMENT: "all"
# docker-compose.prod.yml(生产环境)
version: '3.8'
services:
app:
restart: always
deploy:
replicas: 2
resources:
limits:
cpus: '1.0'
memory: 512M
environment:
DEBUG: "false"
LOG_LEVEL: "warn"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
restart: always
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
environment:
POSTGRES_LOG_STATEMENT: "none"
# 开发(自动加载 override)
docker-compose up -d
# 生产
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 也可以通过环境变量指定
cp .env.prod .env
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
多环境配置是 Compose 的核心能力之一。docker-compose.override.yml 具有特殊地位,当不带 -f 参数直接运行 docker-compose up 时,Compose 会自动寻找并合并 docker-compose.yml 与 docker-compose.override.yml,后者的同名配置会以覆盖方式生效。这种设计理念让开发人员无需每次敲冗长的 -f 参数链。生产环境推荐显式指定配置文件,并把生产级配置独立到 docker-compose.prod.yml 中。合并时遵循字段覆盖原则,例如 environment 字段如果两文件都定义了同名变量,override 文件的值优先。但在生产环境中,更建议通过外部 .env 文件管理差异,而非硬编码在多个 Compose 文件中。
五、健康检查与依赖
version: '3.8'
services:
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
start_period: 5s
app:
build: ./app
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 10s
timeout: 5s
retries: 3
restart: unless-stopped
volumes:
postgres_data:
健康检查的引入解决了微服务架构中常见的启动时序问题。默认情况下 depends_on 只保证容器按顺序创建,但被依赖服务的进程可能仍在初始化中。比如在数据库尚未完成数据恢复时,应用容器就尝试连接,必然导致启动失败。通过指定 condition: service_healthy,Compose 会先轮询被依赖服务的健康状态,只有当返回 healthy 后才继续创建下游服务。配置健康检查时需要注意四个参数的平衡:interval 设置检查频率,过于频繁会消耗资源,timeout 设定单次检查的超时阈值,retries 确定失败后重试次数,start_period 则给应用充足的冷启动时间,避免应用尚在初始化就被误判为不健康。对于生产环境,建议每个关键服务都配置健康检查,并配合 restart 策略实现故障自愈。
六、Compose Specification 新特性
Docker Compose 在 V2 版本中发生了重大变革,不再强制要求 YAML 文件顶部的 version 字段,而是遵循 Compose Specification 标准。新格式让 Compose 文件更加简洁,也更易于维护。
6.1 无 version 字段的新格式
# docker-compose.yml — 新版格式(推荐)
name: myproject
services:
web:
image: nginx:alpine
ports:
- "80:80"
environment:
NGINX_ENTRYPOINT_QUIET_LOGS: "1"
api:
image: node:20-alpine
ports:
- "3000:3000"
environment:
NODE_ENV: production
新版格式通过 name 字段直接指定项目名称,取代了旧版通过目录名推断项目名的方式。这不仅提高了可读性,也避免了在不同目录下运行相同 Compose 文件时产生不同项目名的混乱。新格式还统一了 Docker Compose V2 CLI 和 Docker Swarm 之间的语义差异,使得迁移路径更加平滑。
6.2 Compose Watch 文件同步
开发时频繁修改代码并手动重启容器效率极低。Compose Watch 引入了文件变更自动同步机制,在检测到源码变动后自动执行构建或重启操作。
services:
app:
build:
context: ./app
target: dev
develop:
watch:
- action: sync
path: ./app/src
target: /app/src
- action: rebuild
path: ./app/package.json
- action: sync+restart
path: ./app/config
target: /app/config
ports:
- "3000:3000"
develop.watch 提供了三种动作模式:sync 仅同步文件内容而不重启容器,适用于源码修改;rebuild 在关键构建文件变更时触发镜像重新构建,适合依赖文件如 package.json 或 Cargo.toml 的修改;sync+restart 则兼顾同步与重启,适合配置文件变更的场景。使用 Watch 模式需要将 Docker Desktop 升级到最新版,或在 Linux 上安装 Docker Engine 并启用 BuildKit。
6.3 include 组合多文件
对于大型项目,把数十个服务塞进一个 docker-compose.yml 文件会造成维护困难。include 语法允许将不同模块的配置拆分成独立文件,然后在主文件中引用。
# docker-compose.yml
name: ecommerce-platform
include:
- path: ./infra/postgres-compose.yaml
- path: ./infra/redis-compose.yaml
- path: ./services/api-compose.yaml
- path: ./services/web-compose.yaml
env_file: ./services/web.env
# infra/postgres-compose.yaml
services:
db:
image: postgres:15-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: shop
volumes:
pgdata:
include 在解析阶段将所有引用的文件内容合并到一个配置树中,其效果等效于把各个文件的内容拼接到主文件。每个被包含的文件可以有自己的 env_file,这为多团队协作开发提供了极大的便利。与 extends 不同,include 是完全的包含语义,不会存在字段冲突时的覆盖优先级问题。
七、Profiles 与环境管理
在真实项目中,不同场景下需要启动的服务子集往往不同。比如启动监控系统时不需要数据库,运行 E2E 测试时只需要数据库和测试用应用实例。Docker Compose 的 profiles 特性正是为了解决这种选择性服务编排的需求。
# docker-compose.yml
name: saas-platform
services:
app:
build: ./app
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://db:5432/app
depends_on:
- db
db:
image: postgres:15-alpine
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
prometheus:
image: prom/prometheus:latest
profiles:
- monitoring
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
profiles:
- monitoring
ports:
- "3001:3000"
depends_on:
- prometheus
e2e-tests:
build:
context: ./e2e
dockerfile: Dockerfile.test
profiles:
- test
environment:
TEST_BASE_URL: http://app:3000
depends_on:
- app
- db
mailhog:
image: mailhog/mailhog:latest
profiles:
- dev
- test
ports:
- "1025:1025"
- "8025:8025"
volumes:
db_data:
# 只启动核心服务(app + db)
docker-compose up -d
# 启动核心服务 + 监控栈
docker-compose --profile monitoring up -d
# 启动核心服务 + 测试环境
docker-compose --profile test up -d
# 启动核心服务 + 开发辅助(邮件捕获)
docker-compose --profile dev up -d
# 一次启动多个 Profile
docker-compose --profile monitoring --profile dev up -d
profiles 的设计精髓在于服务默认不会随核心栈启动,只有当对应的 profile 被显式指定时才会被编排。没有声明 profiles 的服务属于默认服务组,是每次启动的基础。一个服务可以关联多个 profile,比如 mailhog 既可以在开发环境中使用,也可以在测试环境中使用。Profile 与 depends_on 的交互也值得注意:即使被依赖服务没有显式声明对应 profile,只要依赖链中有服务需要它,Compose 仍会正确解析启动顺序。
最佳实践中,建议将基础设施类服务(数据库、缓存)归入默认组,工具类服务(监控、日志收集)分配到独立 profile,测试相关服务单独成组。这样开发日常只需要运行核心栈,需要特定能力时再按需激活对应 profile,显著降低了容器的资源消耗。
八、BuildKit 高级构建
BuildKit 是 Docker 的下一代构建引擎,相比传统构建器在性能、缓存和扩展性上有质的飞跃。在 Compose 中启用 BuildKit 后,可以享受并行构建、更智能的缓存和跨平台构建等高级能力。
services:
app:
build:
context: ./app
dockerfile: Dockerfile
target: production
cache_from:
- type=local,src=/tmp/.buildx-cache
cache_to:
- type=local,dest=/tmp/.buildx-cache-new,mode=max
args:
BUILDKIT_INLINE_CACHE: "1"
platforms:
- linux/amd64
- linux/arm64
image: myapp:latest
ports:
- "3000:3000"
# 启用 BuildKit 构建(Docker Engine 23.0+ 默认已启用)
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose build
# 或在 CI 中利用 registry 缓存加速
docker-compose build --progress=plain
BuildKit 的缓存策略分为 inline 和 registry 两种模式。inline 模式将缓存层直接嵌入到最终镜像中,无需额外存储,但会增加镜像体积;registry 模式则将缓存存储在专门的镜像仓库中,适合 CI/CD 流水线跨构建复用。mode=max 参数会缓存构建过程中的所有中间层,包括那些未包含在最终镜像中的层,这在多阶段构建中尤为有效。
多阶段构建在 Compose 中的典型应用如下:
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
EXPOSE 3000
CMD ["node", "dist/main.js"]
在 Compose 中通过 target 字段可以指定使用 Dockerfile 的某个特定阶段。比如开发环境下直接构建到 builder 阶段,保留源码和开发依赖用于调试,而生产环境则只构建到 production 阶段,产出最小化镜像。这种策略能够将生产镜像体积减少百分之七十以上,同时加快部署速度。
九、网络深入
Docker Compose 的默认网络行为足够应对多数场景,但在微服务架构、安全隔离和多主机部署中,深入理解网络模型是关键。
9.1 自定义隔离网络
name: microservices
services:
api-gateway:
image: nginx:alpine
ports:
- "80:80"
networks:
- public
- internal
user-service:
build: ./services/user
networks:
- internal
- database
order-service:
build: ./services/order
networks:
- internal
- database
- message-queue
postgres:
image: postgres:15-alpine
networks:
- database
rabbitmq:
image: rabbitmq:3-management-alpine
networks:
- message-queue
networks:
public:
driver: bridge
internal:
driver: bridge
internal: true
database:
driver: bridge
internal: true
message-queue:
driver: bridge
internal: true
这个配置演示了零信任网络架构。api-gateway 是唯一暴露端口到宿主机的服务,所有内部服务都不直接对外暴露。internal: true 的网络属性阻止了容器通过 NAT 访问外部互联网,有效缩小了攻击面。数据库和消息队列各自拥有独立的网络隔离层,即使某个服务被入侵,横向移动的范围也会被严格限制。在多服务项目中,强烈建议按照数据敏感度划分网络边界,而非全部服务共享同一个默认网络。
9.2 DNS 解析机制
Compose 在每个自定义网络中内置了嵌入式 DNS 服务器。容器之间的服务发现完全通过 DNS 名称完成,例如 user-service 可以直接用 postgres 作为主机名来连接数据库。DNS 解析的优先级规则是:先查找同网络中的服务名,然后是容器名,最后是网络别名。如果多个网络中存在同名服务,解析结果取决于容器所连接的网络顺序。
services:
web:
image: nginx
networks:
frontend:
aliases:
- web-alias
- app-server
backend:
aliases:
- api-backend
networks:
frontend:
backend:
通过 aliases 可以为服务配置额外的 DNS 解析名称,这在蓝绿部署和金丝雀发布中非常实用。不同网络中的别名彼此隔离,不会互相干扰。
十、Volume 高级管理
Compose 的存储管理看似简单,但深入理解 bind mount 与 named volume 的差异,对于数据安全、性能优化和跨环境一致性至关重要。
10.1 Bind Mount 与 Named Volume 对比
services:
dev-app:
build: ./app
volumes:
# Bind Mount:直接映射宿主机目录,实时同步,性能略低
- ./app/src:/app/src:cached
# Named Volume:由 Docker 管理,性能更好,支持驱动扩展
- app_data:/app/data
# Bind Mount 只读模式:防止容器内意外修改源码
- ./app/config:/app/config:ro
postgres:
image: postgres:15-alpine
volumes:
# Named Volume 存储数据库数据,迁移简便
- pg_data:/var/lib/postgresql/data
# 初始化脚本
- ./init-scripts:/docker-entrypoint-initdb.d:ro
volumes:
app_data:
driver: local
pg_data:
driver: local
Bind Mount 在开发环境中几乎是必选项,因为它实现了宿主机和容器之间的实时双向同步。但在操作系统间的文件系统事件通知存在差异,比如 macOS 下的文件变更有时会有数百毫秒的延迟,此时可以使用 delegated、cached 或 consistent 等一致性修饰符来调整。生产环境中应首选 Named Volume,因为它绕过了宿主机的文件系统层,直接由 Docker Storage Driver 管理,I/O 性能更接近原生水平。
10.2 Volume 驱动与远程存储
volumes:
pg_data:
driver: local
driver_opts:
type: nfs
o: addr=nfs-server.example.com,rw
device: ":/exports/postgres"
shared_cache:
driver: local
driver_opts:
type: tmpfs
o: size=100m
device: tmpfs
当应用需要跨主机共享存储时,可以通过 driver_opts 配置 NFS、Ceph 或 AWS EFS 等远程存储后端。对于纯临时数据,如编译缓存或会话存储,tmpfs 类型的 volume 将数据完全放在内存中,既提升了访问速度,又避免了磁盘持久化,容器停止后数据自动释放。
10.3 备份与迁移策略
# 备份 Named Volume 到压缩包
docker-compose exec db pg_dump -U postgres myapp | gzip > backup-$(date +%F).sql.gz
# 使用临时容器打包 Volume
docker run --rm -v $(docker-compose ps -q db | xargs docker inspect -f '{{range .Mounts}}{{.Name}} {{end}}' | awk '{print $1}'):/data -v $(pwd):/backup alpine tar czf /backup/volume-backup.tar.gz -C /data .
# 跨环境迁移 Volume
docker run --rm -v plumephp_postgres_data:/from -v newproject_pg_data:/to alpine sh -c "cp -a /from/. /to/"
定期备份生产数据库 volume 是运维的基本要求。最简单的方式是通过数据库自身的 dump 工具导出逻辑备份,恢复时使用对应 restore 命令。对于物理卷备份,可以借助临时容器挂载两个 volume 进行文件级拷贝。建议在备份脚本中加入健康检查,确保备份开始前数据库处于一致状态。
十一、生产部署与运维
docker-compose 作为单机编排工具,在生产环境中有其适用边界和局限性。理解这些边界有助于正确选择技术方案。
11.1 资源限制与 OOM 防护
services:
app:
image: myapp:latest
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
pids: 500
reservations:
cpus: '0.5'
memory: 256M
ports:
- "3000:3000"
ulimits:
nofile:
soft: 65536
hard: 65536
worker:
image: myworker:latest
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
restart: always
生产环境中必须显式设置 limits 和 reservations。limits 是硬上限,一旦容器超过该阈值会被系统强制终止;reservations 是调度保证,确保宿主机上始终保留足够的 CPU 和内存资源。在 Linux 系统中,如果容器内存使用量达到 limits.memory 的限制,内核的 OOM Killer 会直接杀死进程而不是优雅退出。因此建议应用程序内部实现内存监控,在接近阈值前主动释放缓存或拒绝新请求。ulimits 字段可以调整文件的描述符上限,高并发的网络服务通常需要把这个值设置为数万级别,否则在流量洪峰时会出现连接拒绝的错误。
11.2 日志聚合
services:
app:
image: myapp:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
vector:
image: timberio/vector:latest
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./vector.toml:/etc/vector/vector.toml:ro
profiles:
- logging
fluentd:
image: fluent/fluentd:v1.16
volumes:
- ./fluentd/conf:/fluentd/etc
profiles:
- logging
Docker 默认的 json-file 日志驱动虽然方便,但如果不加限制,单个容器的日志文件会无限增长并最终占满磁盘。max-size 和 max-file 选项能够实施日志轮转策略,避免磁盘空间耗尽。对于中大型系统,应将日志转发到集中式日志平台。Vector 和 Fluentd 是两个优秀的开源日志收集工具,Vector 使用 Rust 编写,性能极高且配置简单;Fluentd 拥有丰富的插件生态,与 Elasticsearch、Loki、S3 等后端集成成熟。
11.3 docker-compose 的局限与迁移路径
docker-compose 天生是单机编排工具,它不提供自动扩缩容、滚动更新、跨主机服务发现等能力。当业务需要高可用或弹性伸缩时,应该考虑迁移到 Docker Swarm 或 Kubernetes。
- Docker Swarm:内置于 Docker Engine,迁移成本最低,一条
docker swarm init命令即可将单机 Compose 扩展到多节点集群,Compose 文件只需少量修改即可作为 Stack 定义部署。 - Kubernetes:业界标准,生态极其丰富,但学习曲线陡峭。
- Kompose:官方提供的自动转换工具,可以将
docker-compose.yml一键转换为 Kubernetes 的 Deployment、Service 和 Ingress 资源定义,是快速上云的有效捷径。
# Kompose 一键转换为 K8s 资源
kompose convert -f docker-compose.yml
# 生成并直接部署到当前 K8s 上下文
kompose up -f docker-compose.yml
在实际迁移过程中,首先要将配置中的 build 字段替换为预构建镜像引用,因为 Kubernetes 节点不负责构建镜像。其次要评估 Stateful 服务的状态,数据库类服务在 K8s 中应优先使用 StatefulSet 而非 Deployment。最后要设计存储类的映射,确保原有的 Named Volume 能够正确对应到 PV 和 PVC。对于大多数中小型 SaaS
项目,如果当前 docker-compose 的方案已能稳定运行,则无需急于迁移到 K8s。只有明确出现单点故障、需要自动水平扩容或团队具备相应运维能力时,才应该启动迁移计划。
相关阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。