假如你本地开发一个项目,需要同时启动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
这种方式的痛点非常明显:
- 命令繁琐:每个容器都要敲一条长命令,参数多(端口、环境变量、挂载),容易输错。
- 依赖混乱:必须按顺序启动(先启动数据库、Redis,再启动后端),手动管理依赖关系。
- 难以维护:命令分散在终端历史里,团队协作时无法共享配置,新人接手要重新敲一遍命令。
- 清理麻烦:停止容器要一个个停,删除容器也要一个个删,容易遗漏。
而用Docker Compose,只需两步:
- 编写
docker-compose.yml,配置所有服务; - 执行
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种情况:
- 本地开发环境:核心场景!开发者无需手动启动多个容器,一键启动整个项目的依赖服务,大幅提升开发效率,避免环境不一致问题。
- 测试环境部署:小型测试环境,可快速部署整套服务,测试完成后一键清理,节省环境搭建时间。
- 单机小型服务部署:比如个人项目、小型网站),无需复杂的集群管理,用Compose就能实现服务的稳定运行和快速维护。
企业级生产环境还是乖乖的用K8s实现容器调度、扩缩容、故障自愈。
五、常见问题
- 服务名写错:操作单个服务时,服务名必须和
docker-compose.yml里services下的名称完全一致,否则会提示“找不到服务”。 - 依赖关系误区:
depends_on只保证启动顺序,不保证服务就绪。解决方法:在后端服务中添加“数据库连接重试”逻辑。 - 数据卷挂载错误:如果挂载路径写错,会导致数据无法持久化,建议用“命名数据卷”,无需手动指定宿主机路径。
- 配置文件格式错误:YAML文件对缩进非常敏感,必须用2个空格缩进!不要用Tab!,否则会报错“配置文件无效”。