Docker Compose:单机容器编排神器!

4 阅读7分钟

假如你本地开发一个项目,需要同时启动Nginx、Gunicorn、MySQL、Redis四个容器,每次启动都要敲4条docker run命令,还要手动配置网络、数据卷、还要一个个启停……

而Docker Compose,就是为解决这个痛点而生的“单机容器编排工具”—— 用一个配置文件,定义所有服务的启动规则,一条命令就能实现“一键启动、一键停止、一键重启”所有容器。

一、Docker Compose到底是什么?

官方定义:Docker Compose是Docker官方提供的「单机容器编排工具」,基于YAML文件定义多个容器的服务配置,通过一条命令就能实现多个容器的协同启动、停止、重启等操作。

优势说明

  • 单一配置文件:所有服务的配置集中在 docker-compose.yml,不用分散管理多个 docker run 命令,便于版本控制和团队协作。
  • 一键操作:一条命令搞定所有服务的启停、重建,无需逐个操作容器,大幅提升效率。
  • 容器协同:自动创建统一网络,让配置在 Compose 里的所有容器,无需手动配置网络就能互相访问。
  • 环境隔离:每个 Compose 项目有独立的网络和容器,不同项目之间互不干扰。

本Compose与K8s的编排有点差别

注意区分:

  • Docker Compose:单机编排,只能管理单个机器上的容器,适合开发、测试、小型单机部署。
  • K8s:集群编排,能管理多台机器(集群)的容器,支持扩缩容、故障自愈,适合企业级生产环境。

简单说:Compose 是“本地/小型场景的利器”,K8s 是“大规模生产场景的重器”,二者不是替代关系,而是互补关系。

二、为什么要用Docker Compose

没有Compose之前,我们操作多容器的流程是这样的:

# 1. 启动数据库容器
docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0

# 2. 启动Redis容器
docker run -d --name redis -p 6379:6379 redis:alpine

# 3. 启动后端容器
docker run -d --name gunicorn -p 8000:8000 --link mysql:mysql --link redis:redis backend:latest

# 4. 启动前端容器
docker run -d --name nginx -p 80:80 frontend:latest

这种方式的痛点非常明显:

  1. 命令繁琐:每个容器都要敲一条长命令,参数多(端口、环境变量、挂载),容易输错。
  2. 依赖混乱:必须按顺序启动(先启动数据库、Redis,再启动后端),手动管理依赖关系。
  3. 难以维护:命令分散在终端历史里,团队协作时无法共享配置,新人接手要重新敲一遍命令。
  4. 清理麻烦:停止容器要一个个停,删除容器也要一个个删,容易遗漏。

而用Docker Compose,只需两步:

  1. 编写 docker-compose.yml,配置所有服务;
  2. 执行 docker-compose up -d,一键启动所有服务。

停止所有服务也只需一条命令:docker-compose down,高效又省心。

三、实操

安装→编写配置文件→执行命令

第一步:安装Docker Compose

注意:Docker默认集成了Docker Compose,安装Docker后直接就能用;Linux系统需要手动安装,命令如下:

# 下载 Compose(注意科学上网)
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装成功
docker-compose --version

出现版本号,说明安装成功。

第二步:编写docker-compose.yml

这是Compose的核心配置文件,大多服务的规则都写在这里。以我的Django项目为例,编写一个完整的配置文件:

version: '3.8'

# 定义所有服务(容器编排)
services:
  # 1. 数据库服务
  mysql:
    image: mysql:8.0  # 使用的镜像
    container_name: mysql  # 容器名称
    ports:
      - "3306:3306"  # 端口映射
    environment:  # 环境变量
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: test_db
      MYSQL_CHARSET: utf8mb4
    volumes:
      - mysql-data:/var/lib/mysql  # 数据卷挂载
    restart: unless-stopped  # 容器退出后自动重启
    
  # 2. Redis服务
  redis:
    image: redis:alpine
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    restart: unless-stopped

  # 3. 后端服务
  gunicorn:
    image: gunicorn:latest
    container_name: gunicorn
    ports:
      - "8000:8000"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/test_db  # 直接用服务名访问mysql
      - SPRING_REDIS_HOST=redis  # 直接用服务名访问redis
    depends_on:
      - mysql
      - redis
    restart: unless-stopped

  # 4. 前端服务
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
    depends_on:
      - backend
    restart: unless-stopped

# 定义数据卷
volumes:
  mysql-data:
  redis-data:

核心配置说明

  • version:Compose版本,建议用3.8。
  • services:所有容器的配置集合,每个子节点就是一个服务(如mysql、redis)。
  • image:服务使用的Docker镜像。
  • ports:端口映射,格式宿主机端口:容器端口,比如3306:3306表示宿主机的3306端口映射到容器的3306端口。
  • environment:环境变量,比如数据库密码、服务配置等,容器内可直接读取。
  • volumes:数据卷挂载,用于持久化数据(先前有提过,可以查看我的专栏)。
  • depends_on:依赖关系,定义服务的启动顺序。

第三步:执行命令

将编写好的docker-compose.yml文件放在任意目录,进入该目录,执行以下命令:

操作多个服务

下表为多业务情况,如集体启动:

操作命令说明
后台启动所有服务docker-compose up -d-d表示后台运行,不会占用终端
停止所有服务docker-compose stop容器仍存在,可通过start快速重启
重启所有服务docker-compose restart适合修改配置后重启,无需重新构建
停止并删除所有服务+容器+网络docker-compose down数据卷不会删除,如需删除加-v参数

操作单个服务

如果只想操作某个服务,只需在命令后加上服务名:

# 启动单个服务
docker-compose up -d redis

# 停止单个服务
docker-compose stop nginx

# 重启单个服务
docker-compose restart mysql

四、适用场景

Compose不是万能的,它的优势集中在「单机场景」,主要适合以下3种情况:

  1. 本地开发环境:核心场景!开发者无需手动启动多个容器,一键启动整个项目的依赖服务,大幅提升开发效率,避免环境不一致问题。
  2. 测试环境部署:小型测试环境,可快速部署整套服务,测试完成后一键清理,节省环境搭建时间。
  3. 单机小型服务部署:比如个人项目、小型网站),无需复杂的集群管理,用Compose就能实现服务的稳定运行和快速维护。

企业级生产环境还是乖乖的用K8s实现容器调度、扩缩容、故障自愈。

五、常见问题

  • 服务名写错:操作单个服务时,服务名必须和docker-compose.ymlservices下的名称完全一致,否则会提示“找不到服务”。
  • 依赖关系误区depends_on只保证启动顺序,不保证服务就绪。解决方法:在后端服务中添加“数据库连接重试”逻辑。
  • 数据卷挂载错误:如果挂载路径写错,会导致数据无法持久化,建议用“命名数据卷”,无需手动指定宿主机路径。
  • 配置文件格式错误:YAML文件对缩进非常敏感,必须用2个空格缩进!不要用Tab!,否则会报错“配置文件无效”。

用人话讲:它就像一个管家,你把所有需要启动的容器(服务)的配置(端口、挂载、依赖、环境变量)都写在一个叫 docker-compose.yml 的文件里,然后告诉这个管家:“启动所有服务”,它就会自动帮你启动所有容器,还会自动配置好容器间的网络,让它们能互相通信。