Docker Compose 实战:从单容器命令到多服务编排

Docker Compose 实战:从单容器命令到多服务编排

    • 引言
    • [一:为什么需要 Docker Compose?](#一:为什么需要 Docker Compose?)
    • [二:Docker Compose 是什么?](#二:Docker Compose 是什么?)
    • [三:快速上手:一个 Nginx + PHP 的实例](#三:快速上手:一个 Nginx + PHP 的实例)
      • [3.1 安装 Docker Compose](#3.1 安装 Docker Compose)
      • [3.2 创建项目目录](#3.2 创建项目目录)
      • [3.3 编写 docker-compose.yml](#3.3 编写 docker-compose.yml)
      • [3.4 启动](#3.4 启动)
      • [3.5 查看运行状态](#3.5 查看运行状态)
    • [四:docker-compose.yml 核心配置项详解](#四:docker-compose.yml 核心配置项详解)
      • [4.1 基础结构](#4.1 基础结构)
      • [4.2 image](#4.2 image)
      • [4.3 container_name](#4.3 container_name)
      • [4.4 ports](#4.4 ports)
      • [4.5 volumes](#4.5 volumes)
      • [4.6 networks](#4.6 networks)
      • [4.7 depends_on](#4.7 depends_on)
    • 五:常用命令一览
      • [5.1 容器生命周期管理](#5.1 容器生命周期管理)
      • [5.2 查看信息](#5.2 查看信息)
      • [5.3 其他实用命令](#5.3 其他实用命令)
    • 六:实战经验与避坑指南
      • [6.1 depends_on 不是万能的](#6.1 depends_on 不是万能的)
      • [6.2 网络通信:服务名即域名](#6.2 网络通信:服务名即域名)
      • [6.3 环境变量的使用](#6.3 环境变量的使用)
      • [6.4 数据持久化](#6.4 数据持久化)
    • 七:总结

引言

作为一名后端开发者,你一定经历过这样的场景:本地开发环境需要同时运行 MySQL、Redis、Nginx 和你的应用服务,每次开机都要手动敲一串长长的 docker run,还要操心网络、顺序、数据卷......一旦换了电脑或者同事接手,又得重新回忆那一堆命令。这不只是麻烦,更是效率的杀手。

直到我遇见了 Docker Compose,才真正体会到"一键启停"的快乐。今天,我就带你深入理解这个工具,并用一个实际例子演示如何用它轻松管理多容器项目。


一:为什么需要 Docker Compose?

让我们先感受一下没有 Compose 的"原始时代"。

假设你要启动一个典型的 Web 项目,包含 MySQL、Redis、后端应用和 Nginx。你需要执行类似这样的命令:

bash 复制代码
# 创建自定义网络
docker network create mynet

# 启动 MySQL
docker run -d --name mysql --network mynet -e MYSQL_ROOT_PASSWORD=root mysql:8.0

# 启动 Redis
docker run -d --name redis --network mynet redis:alpine

# 启动后端(假设已经构建好镜像)
docker run -d --name backend --network mynet -p 8080:8080 my-backend

# 启动 Nginx 代理
docker run -d --name nginx --network mynet -p 80:80 -v ./nginx.conf:/etc/nginx/nginx.conf nginx:alpine

痛点

  • 命令冗长,容易敲错参数。
  • 容器启动顺序需要人工控制(比如后端要等 MySQL 和 Redis 就绪)。
  • 多个容器需要共享网络,手动创建网络并指定。
  • 项目迁移时,需要重新回忆并输入这些命令,不可复制、不可版本化。

而 Docker Compose 正是为解决这些问题而生的。


二:Docker Compose 是什么?

简单来说,Docker Compose 是一个用 YAML 文件定义和运行多个 Docker 容器的工具 。它的核心是一个 docker-compose.yml 文件,里面描述了项目包含哪些服务、每个服务的镜像、端口、数据卷、网络等信息。然后通过一条命令,就能将整个环境创建并启动起来。

本质上,它是将 docker run 的命令行参数"翻译"成了结构化的配置文件,并提供了便捷的管理命令。


三:快速上手:一个 Nginx + PHP 的实例

我们用一个最简单的例子感受一下:启动一个 Nginx 容器和一个 PHP-FPM 容器,让 Nginx 能通过 PHP-FPM 处理 PHP 请求。

3.1 安装 Docker Compose

大多数现代 Linux 发行版都可以通过包管理器直接安装:

bash 复制代码
# CentOS / RHEL
sudo yum install -y docker-compose

# Ubuntu / Debian
sudo apt install -y docker-compose

当然,你也可以从 GitHub 下载最新的二进制文件。

3.2 创建项目目录

bash 复制代码
mkdir -p ~/projects/nginx-php && cd ~/projects/nginx-php

3.3 编写 docker-compose.yml

yaml 复制代码
version: '3.3'

services:
  web_nginx:
    image: nginx:1.24-alpine
    ports:
      - "80:80"
    links:
      - web_php   # 让 nginx 能通过服务名访问 php 容器

  web_php:
    image: php:7-fpm

这个文件定义了两个服务:

  • web_nginx:使用 nginx 镜像,将宿主机的 80 端口映射到容器的 80 端口,并连接到 web_php 服务。
  • web_php:使用 php:7-fpm 镜像,内部暴露 9000 端口供 nginx 调用。

注意links 在较新的 Docker Compose 中已经不是必须的,因为 Compose 会自动为所有服务创建一个默认网络,服务名就可以作为域名互相访问。但这里保留是为了让初学者理解服务间的连接。

3.4 启动

一定要在 docker-compose.yml 所在的目录执行:

bash 复制代码
docker-compose up -d

-d 表示后台运行。

3.5 查看运行状态

bash 复制代码
docker-compose ps

你会看到两个容器已经运行,名称自动被加上项目名前缀(默认是目录名)。

bash 复制代码
          Name                        Command               State          Ports        
---------------------------------------------------------------------------------------
nginx-php_web_nginx_1      /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp
nginx-php_web_php_1        docker-php-entrypoint php-fpm    Up      9000/tcp

此时访问 http://你的服务器IP,会看到 nginx 的默认欢迎页,说明两个容器已经成功协作。


四:docker-compose.yml 核心配置项详解

理解了基本用法,我们来逐一拆解 YAML 文件中常见的配置项。

4.1 基础结构

yaml 复制代码
version: '3.8'      # Compose 文件格式版本,与 Docker 引擎版本对应
services:           # 定义所有的服务(容器)
  服务名1:
    # 该服务的配置
  服务名2:
    # 其他服务的配置

4.2 image

指定服务使用的镜像,相当于 docker run <镜像>

yaml 复制代码
services:
  app:
    image: nginx:1.24-alpine

4.3 container_name

指定容器的自定义名称,如果不写,Compose 会自动生成 项目名_服务名_序号 的格式。

yaml 复制代码
services:
  mysql:
    container_name: my-mysql
    image: mysql:8.0

提示 :自定义名称后,你无法通过 docker-compose scale 进行水平扩展(因为名称会冲突),所以只在单实例服务中使用。

4.4 ports

端口映射,格式为 "宿主机端口:容器端口"

yaml 复制代码
services:
  nginx:
    ports:
      - "80:80"
      - "443:443"

4.5 volumes

数据卷挂载,支持三种方式:

  • 宿主机绝对路径:/host/path:/container/path
  • 相对路径(相对于 docker-compose.yml 所在目录):./data:/container/path
  • 命名卷:先声明,再使用
yaml 复制代码
services:
  web:
    volumes:
      - ./html:/usr/share/nginx/html   # 挂载当前目录下的 html 文件夹
      - /etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro  # 只读挂载

# 声明命名卷
volumes:
  db_data:

命名卷的声明放在顶层 volumes 下,然后在服务中通过卷名引用:

yaml 复制代码
services:
  mysql:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

4.6 networks

指定服务加入的网络。Compose 会自动创建一个默认网络,所有服务都可以通过服务名互相访问。如果需要自定义网络,可以像下面这样:

yaml 复制代码
services:
  nginx:
    networks:
      - frontend
  app:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend

networks:
  frontend:
  backend:

4.7 depends_on

指定服务间的依赖顺序。Compose 会根据 depends_on 的顺序启动容器,但请注意:它只保证容器启动的顺序,不保证容器内的服务已经就绪(比如 MySQL 还没准备好接受连接,后端就启动了)。

yaml 复制代码
services:
  backend:
    depends_on:
      - mysql
      - redis

如果需要等待服务真正就绪,需要借助 wait-for-it 脚本或健康检查。


五:常用命令一览

Docker Compose 的命令几乎都是 docker-compose <子命令> 的形式。以下是我日常最常用的:

5.1 容器生命周期管理

命令 说明
docker-compose up -d 创建并启动所有容器(后台)
docker-compose down 停止并删除所有容器,默认也会删除网络(可通过 -v 同时删除命名卷)
docker-compose start 启动已存在的容器
docker-compose stop 停止正在运行的容器
docker-compose restart 重启所有容器
docker-compose rm 删除已停止的容器(加 -f 强制)

5.2 查看信息

命令 说明
docker-compose ps 列出当前项目容器状态
docker-compose logs 查看容器日志(加 -f 实时跟踪)
docker-compose top 查看每个容器内运行的进程
docker-compose images 列出 Compose 使用的镜像

5.3 其他实用命令

  • docker-compose exec <服务名> <命令>:在运行中的容器内执行命令,例如 docker-compose exec web_nginx sh
  • docker-compose run --rm <服务名> <命令>:运行一次性的命令,完成后自动删除容器,适合执行迁移、测试等。
  • docker-compose up -d --remove-orphans:删除 docker-compose.yml 中已经不存在的"孤儿"容器,保持环境干净。

六:实战经验与避坑指南

6.1 depends_on 不是万能的

如前所述,depends_on 只能保证容器的启动顺序,但容器内服务未必已就绪。例如后端依赖 MySQL,但 MySQL 容器启动后可能还需要几秒才能接受连接。解决方案:

  • 在应用代码中加入重试逻辑。
  • 使用脚本等待(例如 wait-for-it.sh)在 entrypoint 中阻塞直到依赖服务可用。

6.2 网络通信:服务名即域名

在 Compose 创建的网络中,每个服务都可以用 docker-compose.yml 中定义的服务名作为主机名互相访问。例如上面的例子,web_nginx 容器内可以通过 web_php:9000 访问 PHP-FPM,非常方便。

6.3 环境变量的使用

推荐在 Compose 文件中使用 ${VARIABLE} 引用外部环境变量,配合 .env 文件管理不同环境的配置。例如:

yaml 复制代码
services:
  mysql:
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}

然后在同目录下创建 .env 文件:

复制代码
MYSQL_PASSWORD=root123

6.4 数据持久化

数据库等有状态服务一定要使用命名卷或宿主机路径挂载,否则 down 之后数据就会丢失。养成好习惯:在 docker-compose down 时不加 -v,或者明确知道数据卷的位置。


七:总结

Docker Compose 让多容器应用的管理变得像单容器一样简单。通过一个声明式的 YAML 文件,我们可以:

  • 定义完整的应用栈(包括网络、卷、依赖)。
  • 一键启动、停止、重建整个环境。
  • 将环境配置纳入版本控制,团队协作更轻松。

希望这篇实战笔记能帮你快速上手 Docker Compose。下次再搭建开发环境时,别忘了用上它,享受那种"一条命令,万物齐备"的畅快感。

如果你有更多关于 Compose 的技巧或踩坑经历,欢迎在评论区分享!

相关推荐
乾元1 小时前
模型提取:黑盒环境下如何窃取对手的 AI 模型参数
网络·人工智能·安全·web安全·机器学习·架构·系统架构
hrhcode1 小时前
【云原生】二.Kubernetes基础入门:架构详解与环境搭建
云原生·k8s
志栋智能1 小时前
智能巡检自动化解决方案:从“人海战术”到“AI智巡”的效能革命
大数据·运维·人工智能·网络安全·云原生·自动化
Web极客码1 小时前
CentOS 7 删除文件却不释放空间?从 inode、文件描述符到 VFS 的底层原理解析
python·centos·numpy
志栋智能1 小时前
AI驱动的带内自动化巡检:编织IT生态的“智慧神经网络”
大数据·运维·网络·人工智能·神经网络·自动化
键盘鼓手苏苏2 小时前
Flutter for OpenHarmony:injector 轻量级依赖注入库(比 GetIt 更简单的选择) 深度解析与鸿蒙适配指南
css·网络·flutter·华为·rust·harmonyos
2401_858286112 小时前
OS54.【Linux】System V 共享内存(3) “共享内存+管道“修bug记录
linux·运维·服务器·算法·bug
only_Klein2 小时前
kubernetes-Service
云原生·容器·kubernetes
迎仔2 小时前
10-算力中心运维三剑客:Ansible + Jenkins + K8s 高效实战
运维·kubernetes·ansible·jenkins