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数据,尝试启动、查看数据、停止整个系统。

相关推荐
一叶知秋yyds20 小时前
Ubuntu 虚拟机安装 OpenClaw 完整流程
linux·运维·ubuntu·openclaw
斯普信云原生组20 小时前
Prometheus 环境监控虚机 Redis 方案(生产实操版)
运维·docker·容器
喵了几个咪21 小时前
如何在 Superset Docker 容器中安装 MySQL 驱动
mysql·docker·容器·superset
工具罗某人21 小时前
docker compose部署kafka集群搭建
docker·容器·kafka
safestar201221 小时前
ES批量写入性能调优:BulkProcessor 参数详解与实战案例
java·大数据·运维·jenkins
来一颗砂糖橘1 天前
负载均衡的多维深度解析
运维·负载均衡
楠奕1 天前
CentOS7安装GoldenDB单机搭建及常见报错解决方案
linux·运维·服务器
GCTTTTTT1 天前
远程服务器走本地代理
运维·服务器
剑锋所指,所向披靡!1 天前
Linux常用指令(2)
linux·运维·服务器
飞Link1 天前
逆向兼容的桥梁:3to2 自动化降级工具实现全解析
运维·开发语言·python·自动化