从单机到集群:手把手教你用Docker CLI玩转Compose和Swarm(避坑指南)

当你第一次用docker run启动一个容器时,那种"开箱即用"的爽快感让人印象深刻。但现实中的项目往往需要多个服务协同工作——前端、后端、数据库、缓存,这些组件就像一支乐队,单独演奏再好也成不了交响乐。这就是为什么我们需要从单容器管理进阶到多服务编排,而Docker Compose和Swarm正是这条进化之路上的关键工具。

记得我第一次尝试部署一个包含Web服务和MySQL的简单应用时,手动管理两个容器的网络连接和启动顺序简直是一场噩梦。直到发现Compose可以用一个YAML文件定义整个应用栈,才明白什么叫"生产力解放"。后来当流量增长需要扩展到多台服务器时,Swarm又用几行命令就帮我搭建起了容器集群。这中间踩过的坑、解决的问题,正是本文想与你分享的实战经验。

1. 从单容器到多服务:Compose编排实战

1.1 为什么需要Compose?

想象你正在开发一个电商网站,需要同时运行:

  • Node.js前端服务(端口3000)
  • Python后端API(端口5000)
  • MySQL数据库(端口3306)
  • Redis缓存(端口6379)

手动用docker run启动每个容器并配置网络,不仅命令冗长,还容易出错。Compose通过声明式配置解决了这个问题。下面是一个典型的docker-compose.yml文件:

version: '3.8'
services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend

  backend:
    build: ./backend 
    environment:
      DB_HOST: mysql
    ports:
      - "5000:5000"
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - mysql_data:/var/lib/mysql

  redis:
    image: redis:alpine

volumes:
  mysql_data:

这个配置文件清晰地定义了:

  • 四个服务的构建方式和依赖关系
  • 端口映射和环境变量
  • 数据卷持久化
  • 自动创建的默认网络

1.2 Compose核心操作指南

启动整个应用栈只需要一行命令:

docker-compose up -d

常用操作命令对比:

操作单容器命令Compose命令
启动docker rundocker-compose up
停止docker stopdocker-compose down
查看日志docker logsdocker-compose logs
执行命令docker execdocker-compose exec

避坑提示depends_on只控制启动顺序,不保证服务就绪。对于数据库这类需要初始化时间的服务,建议在应用代码中添加重试逻辑。

1.3 网络与存储的进阶配置

Compose会自动为你的应用栈创建专属网络,但有时需要更精细的控制:

networks:
  app_net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

services:
  frontend:
    networks:
      app_net:
        ipv4_address: 172.20.0.2

数据卷同样支持高级配置:

volumes:
  db_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /mnt/volumes/mysql

2. 从单机到集群:Swarm实战入门

2.1 Swarm核心概念解析

当你的应用需要更高可用性或更大规模时,单机部署就力不从心了。Swarm将多台机器组织成一个虚拟的Docker主机,主要概念包括:

  • 节点(Node):集群中的物理机,分为管理节点(Manager)和工作节点(Worker)
  • 服务(Service):要运行的应用组件,可以指定副本数、资源限制等
  • 任务(Task):服务的一个具体运行实例
  • 栈(Stack):一组相关联服务的集合(类似Compose中的项目)

2.2 搭建你的第一个Swarm集群

初始化Swarm集群(在管理节点上执行):

docker swarm init --advertise-addr <MANAGER_IP>

命令会输出加入集群的token,在其他机器上执行类似下面的命令加入集群:

docker swarm join --token SWMTKN-1-xxx <MANAGER_IP>:2377

验证集群状态:

docker node ls

2.3 部署Swarm服务

使用Compose文件部署到Swarm(v3格式):

docker stack deploy -c docker-compose.yml ecommerce

关键Swarm命令对比:

操作Compose命令Swarm命令
部署docker-compose updocker stack deploy
查看服务docker-compose psdocker service ls
扩缩容手动修改YAMLdocker service scale

性能优化:生产环境建议每个服务至少3个管理节点以保证高可用,工作节点根据负载动态扩展。

3. 关键场景深度解析

3.1 网络模型对比

不同环境下的网络特性:

特性单机DockerComposeSwarm
服务发现容器名解析自动DNS内置DNS轮询
负载均衡入口负载均衡
跨主机通信不支持不支持overlay网络

Swarm中创建overlay网络:

docker network create --driver overlay --attachable app_overlay

3.2 存储方案选择

数据持久化策略对比:

方案适用场景Swarm注意事项
本地卷开发环境需确保卷在相同节点
NFS/共享存储生产数据库注意IO性能瓶颈
云存储插件云环境需要额外配置

3.3 滚动更新与健康检查

Swarm的滚动更新配置示例:

services:
  backend:
    image: app/api:v2
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
      restart_policy:
        condition: on-failure

4. 生产环境避坑指南

4.1 常见问题排查

问题1:服务启动但无法访问

  • 检查网络模式:docker network inspect
  • 验证端口发布:docker service inspect --pretty

问题2:节点资源不足

  • 设置资源限制:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    

4.2 安全最佳实践

  • 使用Swarm secrets管理敏感信息:

    echo "db_password" | docker secret create db_pass -
    
  • 限制管理节点访问:

    docker swarm update --autolock=true
    

4.3 监控与日志方案

推荐工具组合:

  • Prometheus + Grafana:监控集群状态
  • ELK:集中日志收集
  • cAdvisor:容器指标采集

基础监控命令:

docker stats
docker service logs --follow backend

5. 从开发到生产的完整工作流

5.1 本地开发阶段

使用Compose的override文件实现环境差异化:

# docker-compose.override.yml
services:
  backend:
    volumes:
      - ./src:/app/src
    environment:
      DEBUG: "true"

5.2 CI/CD集成

典型部署流程:

  1. 构建镜像并推送到仓库
  2. 更新Compose文件中的镜像版本
  3. 执行滚动更新:
    docker stack deploy -c docker-compose.prod.yml ecommerce
    

5.3 蓝绿部署实现

通过标签实现流量切换:

docker service update --image app/api:v2 --container-label-add version=v2 backend

然后更新负载均衡器配置,逐步将流量导向v2版本容器。

更多推荐