Docker Compose:多容器应用编排入门与实战

在实际开发中,很少有应用是单容器运行的------一个完整的系统可能需要Web容器、数据库容器、缓存容器(如Redis)相互配合。比如一个电商网站,至少需要:

  • Nginx容器(处理静态资源和反向代理);
  • 后端API容器(如Spring Boot);
  • MySQL容器(存储订单和用户数据)。

如果手动逐个启动这些容器,不仅要记住复杂的docker run参数(端口映射、数据挂载、网络配置),还要保证启动顺序(必须先启动MySQL,再启动API),一旦参数记错就会导致整个系统运行失败。

而Docker Compose就是为解决这个问题而生的工具------用一个配置文件定义多容器应用的所有组件,然后用一条命令启动/停止整个系统。本章将带你掌握Compose的核心用法,从配置文件编写到实战编排,让多容器管理变得简单。

一、为什么需要Docker Compose?先看"手动操作"的痛点 😫

假设我们要部署一个"Nginx+MySQL+Spring Boot"的Web应用,手动操作需要:

  1. 启动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
  1. 等待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
  1. 最后启动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,只需要:

  1. 编写一个docker-compose.yml配置文件,定义所有容器的参数;
  2. 执行docker-compose up -d一键启动整个系统;
  3. 执行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:启动并验证整个系统

  1. 启动所有服务 :在myapp目录下执行(首次启动会构建API镜像,可能需要几分钟):
bash 复制代码
docker-compose up -d
  1. 查看服务状态 :确认所有服务都是Up状态:
bash 复制代码
docker-compose ps
  1. 验证功能

    • 访问localhost(Nginx端口),会被转发到API服务;

    • 若API接口正常,应能查询到MySQL中初始化的user数据;

    • 查看日志排查问题(如API连接数据库失败):

      bash 复制代码
      docker-compose logs -f api  # 实时查看API日志
  2. 停止并清理:测试完成后,停止所有服务(数据卷会保留,下次启动数据不丢失):

bash 复制代码
docker-compose down

六、避坑指南:Compose新手常犯的3个错误 ❌→✅

  1. depends_on不保证服务"就绪"

    → 问题:depends_on: - mysql只能保证MySQL先启动,但不能保证MySQL完全就绪(如初始化完成),可能导致API启动时连接失败。

    → 解决:在应用中添加"重试机制"(如Spring Boot的spring.datasource.hikari.connection-timeout),或使用第三方工具(如wait-for-it)检测服务就绪状态。

  2. YAML配置缩进错误

    → 问题:YAML对缩进敏感(必须用空格,不能用Tab),缩进错误会导致配置解析失败。

    → 解决:用IDE(如VS Code)的YAML插件自动校验,或在线工具(如YAML Lint)检查格式。

  3. 服务间通信失败

    → 问题:容器间无法通过服务名通信(如api服务访问mysql:3306失败)。

    → 解决:确保所有服务在同一个网络中(Compose默认会创建一个网络,所有服务自动加入,除非显式指定其他网络)。

七、总结:Compose的核心价值与下一步 🎯

Docker Compose的核心价值是**"简化多容器管理"**------用一个配置文件集中定义所有服务,用一条命令操作整个系统,大幅降低了多容器应用的部署和维护成本。

掌握Compose后,你可以轻松编排各种复杂架构(如微服务、分布式系统)。下一章,我们将通过更多实战场景(部署前端项目、Python爬虫、Redis集群等),让你熟练运用Compose解决实际问题。

小练习:用Compose编排一个"Redis+Python爬虫"应用------Python爬虫将数据存入Redis,用数据卷持久化Redis数据,尝试启动、查看数据、停止整个系统。

相关推荐
C2H5OH6662 小时前
Podman和Docker
docker·容器·podman
毛甘木2 小时前
阿里云CentOS环境下Docker使用教程
阿里云·docker·centos
AAA小肥杨2 小时前
探索K8s与AI的结合:PyTorch训练任务在k8s上调度实践
人工智能·pytorch·docker·ai·云原生·kubernetes
jason.zeng@15022072 小时前
my.cnf详解
运维·数据库·adb
灵神翁2 小时前
自建node云函数服务器
运维·服务器
春生野草3 小时前
安装k8s过程中涉及知识点梳理
docker
TangDuoduo00053 小时前
【IO模型与并发服务器】
运维·服务器·网络·tcp/ip
FOREVER-Q3 小时前
Windows 下 Docker Desktop 快速入门与镜像管理
运维·服务器·windows·docker·容器
地球没有花3 小时前
gitlab cicd首次操作
运维·git·ci/cd·gitlab