在实际开发中,很少有应用是单容器运行的------一个完整的系统可能需要Web容器、数据库容器、缓存容器(如Redis)相互配合。比如一个电商网站,至少需要:
- Nginx容器(处理静态资源和反向代理);
- 后端API容器(如Spring Boot);
- MySQL容器(存储订单和用户数据)。
如果手动逐个启动这些容器,不仅要记住复杂的docker run参数(端口映射、数据挂载、网络配置),还要保证启动顺序(必须先启动MySQL,再启动API),一旦参数记错就会导致整个系统运行失败。
而Docker Compose就是为解决这个问题而生的工具------用一个配置文件定义多容器应用的所有组件,然后用一条命令启动/停止整个系统。本章将带你掌握Compose的核心用法,从配置文件编写到实战编排,让多容器管理变得简单。
一、为什么需要Docker Compose?先看"手动操作"的痛点 😫
假设我们要部署一个"Nginx+MySQL+Spring Boot"的Web应用,手动操作需要:
- 启动MySQL容器(指定端口、数据卷、密码):
bash
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容器(指定数据库地址、端口):
bash
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):
bash
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或下载二进制文件),具体步骤可参考官方文档。
验证安装是否成功:
bash
docker-compose --version # 输出类似 docker-compose version v2.20.3 的版本信息
三、docker-compose.yml配置文件:多容器的"说明书" 📝
docker-compose.yml是Compose的核心,所有容器的配置都集中在这里。它的语法遵循YAML规范(严格缩进,用空格不用Tab),基本结构如下:
yaml
# 版本号(需与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:编写各组件配置
1. Nginx配置(nginx/nginx.conf)
实现反向代理,将根路径请求转发到API服务(服务名api,容器内端口8080):
nginx
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;
}
}
2. Spring Boot的Dockerfile(api/Dockerfile)
基于Java镜像构建API服务:
dockerfile
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)
3. MySQL初始化脚本(mysql/init.sql)
启动时自动创建数据库和测试表:
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');
4. 核心:docker-compose.yml配置
yaml
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镜像,可能需要几分钟):
bash
docker-compose up -d
- 查看服务状态 :确认所有服务都是
Up状态:
bash
docker-compose ps
-
验证功能:
-
访问
localhost(Nginx端口),会被转发到API服务; -
若API接口正常,应能查询到MySQL中初始化的
user数据; -
查看日志排查问题(如API连接数据库失败):
bashdocker-compose logs -f api # 实时查看API日志
-
-
停止并清理:测试完成后,停止所有服务(数据卷会保留,下次启动数据不丢失):
bash
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数据,尝试启动、查看数据、停止整个系统。