在实际开发中,很少有应用是单容器运行的——一个完整的系统可能需要Web容器、数据库容器、缓存容器(如Redis)相互配合。比如一个电商网站,至少需要:
Nginx容器(处理静态资源和反向代理); 后端API容器(如Spring Boot); MySQL容器(存储订单和用户数据)。 如果手动逐个启动这些容器,不仅要记住复杂的docker run参数(端口映射、数据挂载、网络配置),还要保证启动顺序(必须先启动MySQL,再启动API),一旦参数记错就会导致整个系统运行失败。
而Docker Compose就是为解决这个问题而生的工具——用一个配置文件定义多容器应用的所有组件,然后用一条命令启动/停止整个系统。本章将带你掌握Compose的核心用法,从配置文件编写到实战编排,让多容器管理变得简单。
一、为什么需要Docker Compose?先看“手动操作”的痛点 😫 假设我们要部署一个“Nginx+MySQL+Spring Boot”的Web应用,手动操作需要:
启动MySQL容器(指定端口、数据卷、密码):
docker run -d -p 3306:3306 -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name app-mysql mysql:5.7
等待MySQL启动完成(否则API连接会失败),再启动Spring Boot容器(指定数据库地址、端口):
docker run -d -p 8080:8080 -e SPRING_DATASOURCE_URL=jdbc:mysql://app-mysql:3306/test --name app-api my-springboot-app:v1
最后启动Nginx容器(映射端口,反向代理到API):
docker run -d -p 80:80 -v ./nginx.conf:/etc/nginx/conf.d/default.conf --name app-nginx nginx:alpine
这个过程的问题很明显:
步骤繁琐,每次部署都要重复输入3条命令,容易输错参数;
依赖关系难保证(必须先启动MySQL,否则API启动失败);
停止/删除时也要逐个操作(docker stop app-nginx app-api app-mysql);
配置分散在命令中,团队协作时难以共享和维护。
而用Docker Compose,只需要:
编写一个docker-compose.yml配置文件,定义所有容器的参数;
执行docker-compose up -d一键启动整个系统;
执行docker-compose down一键停止并清理所有容器。
二、Docker Compose核心概念:配置文件+命令行工具 🛠️ Docker Compose由两部分组成:
配置文件(默认docker-compose.yml):用YAML格式定义多容器应用的所有服务(容器)、网络、数据卷等;
命令行工具(docker-compose):通过命令解析配置文件,实现多容器的批量启动、停止、重启等操作。
安装Docker Compose(通常无需手动安装)
Windows/macOS:安装Docker Desktop时会自动附带Compose,无需额外操作;
Linux:需要手动安装(推荐用pip或下载二进制文件),具体步骤可参考官方文档。
验证安装是否成功:
docker-compose --version # 输出类似 docker-compose version v2.20.3 的版本信息
三、docker-compose.yml配置文件:多容器的“说明书” 📝 docker-compose.yml是Compose的核心,所有容器的配置都集中在这里。它的语法遵循YAML规范(严格缩进,用空格不用Tab),基本结构如下:
# 版本号(需与Docker版本兼容,推荐3.x)
version: '3.8'
# 定义所有服务(容器)
services:
服务1名称:
配置项1: 值
配置项2: 值
服务2名称:
配置项1: 值
# 定义数据卷(可选,与docker volume对应)
volumes:
卷1名称:
卷2名称:
# 定义网络(可选,默认会创建一个桥接网络)
networks:
网络1名称:
核心配置项详解(services下的常用配置)
配置项 作用 示例
image 指定容器使用的镜像 image: mysql:5.7
build 从本地Dockerfile构建镜像(代替image) build: ./api(Dockerfile在./api目录)
ports 端口映射(主机端口:容器端口) ports: - "8080:8080"
volumes 数据挂载(数据卷/主机路径:容器路径) volumes: - mysql-data:/var/lib/mysql
environment 设置环境变量(键值对) environment: - MYSQL_ROOT_PASSWORD=123456
depends_on 定义服务依赖(控制启动顺序) depends_on: - mysql(依赖mysql服务)
restart 容器重启策略(如always:总是重启) restart: always
networks 指定容器加入的网络 networks: - app-network
四、Compose常用命令:一键管理多容器 🔧 掌握以下命令,就能应对日常90%的操作:
命令 作用 示例
docker-compose up 创建并启动所有服务(前台运行) docker-compose up
docker-compose up -d 后台启动所有服务(推荐) docker-compose up -d
docker-compose down 停止并删除所有服务、网络(保留数据卷) docker-compose down
docker-compose ps 查看所有服务状态 docker-compose ps
docker-compose logs 查看服务日志(可指定服务名) docker-compose logs api(查看api服务日志)
docker-compose logs -f 实时跟踪日志 docker-compose logs -f mysql
docker-compose start 启动已停止的服务 docker-compose start
docker-compose stop 停止运行中的服务 docker-compose stop
docker-compose restart 重启所有服务 docker-compose restart
五、实战:用Compose编排“Nginx+MySQL+Spring Boot”应用 🏗️ 我们以一个经典的Web架构为例,演示如何用Compose编排多容器应用。目标:
Nginx作为反向代理,将localhost的请求转发到后端API; Spring Boot API连接MySQL数据库,提供简单的查询接口; 所有数据(MySQL数据、API日志)持久化存储。 步骤1:准备项目结构 在本地创建如下目录结构:
myapp/
├── docker-compose.yml # Compose配置文件
├── nginx/
│ └── nginx.conf # Nginx配置(反向代理)
├── api/
│ └── Dockerfile # 构建Spring Boot镜像的Dockerfile
│ └── app.jar # Spring Boot应用jar包(假设已打包好)
└── mysql/
└── init.sql # MySQL初始化脚本(创建数据库和表)
步骤2:编写各组件配置
-
Nginx配置(nginx/nginx.conf) 实现反向代理,将根路径请求转发到API服务(服务名api,容器内端口8080):
server { listen 80; server_name localhost;
location / { proxy_pass http://api:8080; # 转发到api服务 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }}
-
Spring Boot的Dockerfile(api/Dockerfile) 基于Java镜像构建API服务:
FROM openjdk:17-jre-slim WORKDIR /app COPY app.jar app.jar EXPOSE 8080 CMD ["java", "-jar", "app.jar"] (假设Spring Boot应用的数据库配置已通过环境变量读取,如SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/test) -
MySQL初始化脚本(mysql/init.sql) 启动时自动创建数据库和测试表:
CREATE DATABASE IF NOT EXISTS test; USE test; CREATE TABLE IF NOT EXISTS user ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL ); INSERT INTO user (name) VALUES ('Compose Test'); -
核心:docker-compose.yml配置
version: '3.8' # 定义服务 services: # MySQL服务 mysql: image: mysql:5.7 ports: - "3306:3306" # 主机3306映射到容器3306 volumes: - mysql-data:/var/lib/mysql # 数据卷持久化数据 - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化脚本 environment: - MYSQL_ROOT_PASSWORD=123456 # root密码 - MYSQL_DATABASE=test # 自动创建test数据库 restart: always # 容器退出时自动重启 networks: - app-network # 加入自定义网络 # Spring Boot API服务 api: build: ./api # 从./api目录的Dockerfile构建镜像 ports: - "8080:8080" volumes: - api-logs:/app/logs # 持久化日志 environment: - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/test # 连接mysql服务(用服务名作为主机名) - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=123456 depends_on: - mysql # 依赖mysql服务,确保mysql先启动 restart: always networks: - app-network # Nginx服务 nginx: image: nginx:alpine ports: - "80:80" # 主机80端口映射到容器80 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf # 绑定挂载配置文件 depends_on: - api # 依赖api服务 restart: always networks: - app-network # 定义数据卷 volumes: mysql-data: # 存储MySQL数据 api-logs: # 存储API日志 # 定义自定义网络(默认会创建,显式定义更清晰) networks: app-network: driver: bridge # 桥接网络,服务间可通过服务名通信 步骤3:启动并验证整个系统 启动所有服务:在myapp目录下执行(首次启动会构建API镜像,可能需要几分钟): docker-compose up -d
查看服务状态:确认所有服务都是Up状态:
docker-compose ps
验证功能:
访问localhost(Nginx端口),会被转发到API服务; 若API接口正常,应能查询到MySQL中初始化的user数据; 查看日志排查问题(如API连接数据库失败): docker-compose logs -f api # 实时查看API日志
停止并清理:测试完成后,停止所有服务(数据卷会保留,下次启动数据不丢失):
docker-compose down
六、避坑指南:Compose新手常犯的3个错误 ❌→✅
depends_on不保证服务“就绪”
→ 问题:depends_on: - mysql只能保证MySQL先启动,但不能保证MySQL完全就绪(如初始化完成),可能导致API启动时连接失败。
→ 解决:在应用中添加“重试机制”(如Spring Boot的spring.datasource.hikari.connection-timeout),或使用第三方工具(如wait-for-it)检测服务就绪状态。
YAML配置缩进错误
→ 问题:YAML对缩进敏感(必须用空格,不能用Tab),缩进错误会导致配置解析失败。
→ 解决:用IDE(如VS Code)的YAML插件自动校验,或在线工具(如YAML Lint)检查格式。
服务间通信失败
→ 问题:容器间无法通过服务名通信(如api服务访问mysql:3306失败)。
→ 解决:确保所有服务在同一个网络中(Compose默认会创建一个网络,所有服务自动加入,除非显式指定其他网络)。
七、总结:Compose的核心价值与下一步 🎯
Docker Compose的核心价值是**“简化多容器管理”**——用一个配置文件集中定义所有服务,用一条命令操作整个系统,大幅降低了多容器应用的部署和维护成本。
掌握Compose后,你可以轻松编排各种复杂架构(如微服务、分布式系统)。下一章,我们将通过更多实战场景(部署前端项目、Python爬虫 、Redis集群等),让你熟练运用Compose解决实际问题。
小练习:用Compose编排一个“Redis+Python爬虫”应用——Python爬虫将数据存入Redis,用数据卷持久化Redis数据,尝试启动、查看数据、停止整个系统。