Docker Compose 实战:简化多容器应用管理与部署

在现代微服务架构和复杂应用部署中,我们常常需要同时管理和运行多个相互依赖的 Docker 容器(例如,Web 应用 + 数据库 + 缓存服务)。手动使用 docker run 命令逐一启动、配置和连接这些容器,不仅繁琐易错,而且难以维护和复现。

Docker Compose 应运而生,它是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个单独的 YAML 文件(通常是 docker-compose.yaml),你可以配置应用程序所需的所有服务(容器)、网络、卷以及它们之间的依赖关系。然后,使用简单的命令,就可以一键创建、启动、停止和重建整个应用环境。

本文将深入探讨 Docker Compose 的核心概念和常用操作,并通过两个实例——一个简单的双服务应用和一个真实的 Zabbix 监控系统部署——展示其在实际生产环境中的强大威力。

一、 Docker Compose 核心概念

  • 服务 (Services): 一个服务对应一个应用容器。它定义了该容器的配置,例如使用的镜像 (image)、构建指令 (build)、端口映射 (ports)、环境变量 (environment)、依赖关系 (depends_on)、重启策略 (restart) 等。
  • 项目 (Project): 由 docker-compose.yaml 文件定义的一组相关服务构成一个项目。Compose 会为项目创建一个默认的网络,使得项目内的服务可以通过服务名相互访问。项目名称通常基于包含 docker-compose.yaml 的目录名。
  • YAML 文件 (docker-compose.yaml): Compose 的配置文件,采用 YAML 格式,描述了整个多容器应用的架构。

二、 实战案例 1:构建并管理简单的双服务应用

假设我们需要部署两个简单的 Web 游戏服务:doudizhu (斗地主) 和 motuo (摩托)。每个服务都基于 Nginx,并包含各自的应用代码。

1. 项目结构

/oldboyedu/docker-compose/01-motuo-doudizhu/
├── docker-compose.yaml
└── dockerfile/
    ├── code/
    │   ├── oldboyedu-doudizhu.tar.gz
    │   └── oldboyedu-motuo.tar.gz
    ├── config/
    │   ├── doudizhu.conf
    │   └── motuo.conf
    ├── scripts/
    │   └── start.sh
    ├── doudizhu.dockerfile
    └── motuo.dockerfile

2. Docker Compose 配置文件 (docker-compose.yaml)

# 声明 docker compose 的版本号
version: '3.8'

# 定义需要管理的服务
services:
   # 斗地主服务定义
   doudizhu:
     # 指定最终镜像的名称和标签
     image: linux92-games:doudizhu-v0.1
     # 指定镜像的构建信息 (如果本地没有该镜像,Compose 会执行构建)
     build:
      # 指定构建上下文路径 (Dockerfile 中 ADD/COPY 指令的相对路径起点)
      # './dockerfile' 表示 docker-compose.yaml 同级目录下的 dockerfile 文件夹
      context: ./dockerfile
      # 指定用于构建该服务的 Dockerfile 文件名
      dockerfile: doudizhu.dockerfile

   # 摩托服务定义
   motuo:
     image: linux92-games:motuo-v0.1
     build:
       context: ./dockerfile
       dockerfile: motuo.dockerfile

解释:

  • version: '3.8': 指定了 Compose 文件格式的版本。
  • services: 包含所有要管理的服务定义。
  • doudizhu:motuo:: 自定义的服务名称。
  • image:: 定义了服务最终使用的镜像名称和标签。
  • build:: 如果指定了 build,Compose 会在需要时(如镜像不存在或强制重建)根据提供的 contextdockerfile 构建镜像。
    • context: 定义了构建上下文的路径。所有 Dockerfile 中的 COPYADD 指令都是相对于这个路径的。
    • dockerfile: 指定了用于构建该服务镜像的 Dockerfile 文件名。

3. Dockerfile 文件 (doudizhu.dockerfile, motuo.dockerfile)

这两个 Dockerfile 非常相似,都基于 Alpine Linux,安装 Nginx 和 SSH,配置 SSH 允许 Root 登录,生成 SSH 密钥,并将 Nginx 日志重定向到标准输出/错误流(参考上一篇关于日志管理的文章)。主要区别在于 ADDCOPY 指令,它们分别添加了各自的游戏代码压缩包和 Nginx 配置文件。

  • doudizhu.dockerfile: (内容如您原文所示,添加 oldboyedu-doudizhu.tar.gz,复制 doudizhu.conf)
  • motuo.dockerfile: (内容如您原文所示,添加 oldboyedu-motuo.tar.gz,复制 motuo.conf)
  • start.sh: (内容如您原文所示,用于启动 sshd 和 nginx)

4. Docker Compose 基本操作

在包含 docker-compose.yaml 文件的目录 (/oldboyedu/docker-compose/01-motuo-doudizhu/) 下执行以下命令:

  • 构建镜像 (build): 如果 docker-compose.yaml 中定义了 build 指令,此命令会根据配置构建或重新构建服务的镜像。

    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose build
    # ... (构建过程输出,会利用缓存) ...
    Successfully tagged linux92-games:motuo-v0.1
    Successfully tagged linux92-games:doudizhu-v0.1
    
  • 后台创建并启动容器 (up -d): 这是最常用的命令,它会根据 docker-compose.yaml 创建(如果不存在)并启动所有服务。-d 参数表示在后台 (detached) 模式运行。

    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose up -d
    [+] Running 2/2
     ✔ Container 01-motuo-doudizhu-doudizhu-1  Started
     ✔ Container 01-motuo-doudizhu-motuo-1     Started
    

    Compose 会自动创建默认网络,并将两个服务的容器连接到该网络。容器名称通常是 <project_name>-<service_name>-<instance_number> 的格式。

  • 查看服务状态 (ps): 显示项目中所有容器的状态信息。

    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose ps
    NAME                           IMAGE                         COMMAND                  SERVICE    CREATED          STATUS          PORTS
    01-motuo-doudizhu-doudizhu-1   linux92-games:doudizhu-v0.1   "/bin/sh -x /start.sh"   doudizhu   2 minutes ago    Up 2 minutes    22/tcp, 80/tcp
    01-motuo-doudizhu-motuo-1      linux92-games:motuo-v0.1      "/bin/sh -x /start.sh"   motuo      2 minutes ago    Up 2 minutes    22/tcp, 80/tcp
    
  • 停止服务 (stop): 停止正在运行的服务容器,但不删除它们。-t 参数指定停止超时时间(秒),-t 0 表示立即停止。

    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose stop -t 0
    [+] Stopping 2/2
     ✔ Container 01-motuo-doudizhu-doudizhu-1  Stopped
     ✔ Container 01-motuo-doudizhu-motuo-1     Stopped
    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose ps
    # (无输出,因为容器已停止)
    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker ps -a
    # (可以看到容器状态为 Exited)
    
  • 启动已停止的服务 (start): 启动之前被 stop 命令停止的服务容器。

    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose start
    [+] Running 2/2
     ✔ Container 01-motuo-doudizhu-motuo-1     Started
     ✔ Container 01-motuo-doudizhu-doudizhu-1  Started
    
  • 重启服务 (restart): 重启正在运行的服务。可以指定服务名只重启特定服务,或不指定服务名重启所有服务。

    # 重启 doudizhu 服务
    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose restart doudizhu
    [+] Restarting 1/1
     ✔ Container 01-motuo-doudizhu-doudizhu-1  Started
    

    温馨提示: 服务名 (doudizhu, motuo) 是在 docker-compose.yaml 文件的 services 下定义的键名。

  • 停止并删除容器、网络 (down): 停止所有服务容器,并删除up 命令创建的容器、网络和(可选的)卷。这是清理环境的常用命令。-t 参数同样适用。

    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker-compose down -t 0
    [+] Running 3/3
     ✔ Container 01-motuo-doudizhu-motuo-1     Removed
     ✔ Container 01-motuo-doudizhu-doudizhu-1  Removed
     ✔ Network 01-motuo-doudizhu_default       Removed
    root@docker101:/oldboyedu/docker-compose/01-motuo-doudizhu# docker ps -a
    # (无输出,容器已被删除)
    

三、 添加端口映射和重启策略

我们可以进一步在 docker-compose.yaml 中定义端口映射和容器重启策略。

# 声明docker compose的版本号
version: '3.8'

# 定义常用的服务
services:
   # 斗地主服务
   doudizhu:
     image: linux92-games:doudizhu-v0.1
     # 配置端口映射: [HOST_PORT]:[CONTAINER_PORT]
     ports:
       - "2481:80"    # 将宿主机的 2481 端口映射到容器的 80 端口
       - "2422:22"    # 将宿主机的 2422 端口映射到容器的 22 端口
     # 配置重启策略
     # always: 无论退出状态码是什么,总是重启容器
     # no: (默认) 不自动重启
     # on-failure[:max_retries]: 仅在非 0 退出时重启,可选指定最大重试次数
     # unless-stopped: 总是重启,除非容器被手动停止 (docker stop)
     restart: always
     build:
       context: ./dockerfile
       dockerfile: doudizhu.dockerfile

   # 摩托服务
   motuo:
     image: linux92-games:motuo-v0.1
     # 配置端口映射: 将容器端口映射到宿主机的随机端口
     ports:
       - ":80"        # 宿主机随机端口 -> 容器 80
       - ":22"        # 宿主机随机端口 -> 容器 22
     # (未指定 restart,默认为 no)
     build:
       context: ./dockerfile
       dockerfile: motuo.dockerfile

修改 docker-compose.yaml 后,通常需要重新执行 docker-compose up -d 来应用更改。如果修改了 Dockerfile,可能需要先执行 docker-compose build 或使用 docker-compose up -d --build

四、 实战案例 2:一键部署 Zabbix 监控系统

Docker Compose 非常适合部署像 Zabbix 这样由多个组件构成的复杂应用。

  • docker-compose.yaml (/oldboyedu/docker-compose/02-zabbix/docker-compose.yaml)
version: '3.8'

services:
   # MySQL 数据库服务
   mysql-server:
     image: mysql:8.3.0-oracle
     container_name: mysql-server # 指定固定容器名
     restart: unless-stopped     # 推荐的生产环境重启策略
     environment:                 # 通过环境变量配置 MySQL
       MYSQL_ROOT_PASSWORD: oldboyedu
       MYSQL_DATABASE: zabbix
       MYSQL_USER: linux92
       MYSQL_PASSWORD: "123456"
     networks:                    # 连接到自定义网络
       - zabbix-net
     # MySQL 8 需要指定字符集和认证插件以兼容 Zabbix
     command: ["--character-set-server=utf8", "--collation-server=utf8_bin", "--default-authentication-plugin=mysql_native_password"]

   # Zabbix Java Gateway (用于 JMX 监控)
   zabbix-java-gateway:
     container_name: zabbix-java-gateway
     image: zabbix/zabbix-java-gateway:alpine-6.4-latest
     restart: unless-stopped
     networks:
       - zabbix-net

   # Zabbix Server 服务
   zabbix-server:
     container_name: zabbix-server-mysql
     depends_on:                  # 声明依赖关系,确保 DB 先启动
       - mysql-server
       # - zabbix-java-gateway # 可选,如果 server 配置需要连接 gateway
     image: zabbix/zabbix-server-mysql:alpine-6.4-latest
     restart: unless-stopped
     environment:                 # 配置 Zabbix Server 连接 DB 和 Java Gateway
       DB_SERVER_HOST: mysql-server # 使用服务名作为主机名
       MYSQL_DATABASE: zabbix
       MYSQL_USER: linux92
       MYSQL_PASSWORD: "123456"
       MYSQL_ROOT_PASSWORD: oldboyedu # 可能用于初始化检查
       ZBX_JAVAGATEWAY: zabbix-java-gateway # Java Gateway 的服务名
     networks:
       - zabbix-net
     ports:                       # 暴露 Zabbix Server Agent 监听端口
       - "10051:10051"

   # Zabbix Web UI (Nginx + PHP-FPM) 服务
   zabbix-web-nginx-mysql:
     container_name: zabbix-web-nginx-mysql
     depends_on:                  # 依赖 Zabbix Server
       - zabbix-server
       # - mysql-server # Web UI 也需要直连 DB
     image: zabbix/zabbix-web-nginx-mysql:alpine-6.4-latest
     ports:                       # 暴露 Web 访问端口
       - "80:8080"                # 宿主机 80 映射到容器 8080
     restart: unless-stopped
     environment:                 # 配置 Web UI 连接 DB
       DB_SERVER_HOST: mysql-server
       MYSQL_DATABASE: zabbix
       MYSQL_USER: linux92
       MYSQL_PASSWORD: "123456"
       # MYSQL_ROOT_PASSWORD: oldboyedu # Web UI 通常不需要 root 密码
       # ZBX_SERVER_HOST: zabbix-server # Web UI 需要知道 Server 在哪
     networks:
       - zabbix-net

# 自定义网络定义
networks:
  zabbix-net:
     name: oldboyedu-zabbix    # 指定网络名称
     driver: bridge             # 使用默认的 bridge 驱动
     ipam:                      # IP 地址管理 (可选,用于静态分配)
       driver: default
       config:
         - subnet: 172.20.100.0/16
           gateway: 172.20.100.254
     labels:                     # 为网络添加元数据标签
       school.oldboyedu.com: "老男孩IT教育"
       class.oldboyedu.com: "Linux92"
       auther.oldboyedu.com: "JasonYIN"

关键点分析:

  • 多服务协作: 定义了四个核心服务:MySQL 数据库、Zabbix Server、Zabbix Java Gateway 和 Zabbix Web UI。
  • 镜像使用: 直接使用了官方提供的预构建镜像。
  • 环境变量配置: 通过 environment 向各个服务传递数据库连接信息、密码等配置,避免硬编码。
  • 服务发现: 在自定义网络 zabbix-net 中,服务可以通过其服务名(如 mysql-server, zabbix-server)相互访问,Compose 提供了内置的 DNS 解析。
  • 依赖管理: 使用 depends_on 确保服务按正确的顺序启动(例如,Zabbix Server 依赖于 MySQL)。注意:depends_on 只保证容器启动顺序,不保证服务内部完全就绪。对于需要等待服务就绪的场景,可能需要额外的健康检查或等待脚本。
  • 自定义网络: 创建了一个名为 oldboyedu-zabbix 的独立网络,提供了更好的隔离性,并允许进行 IP 地址规划。
  • 端口映射: 只将需要从宿主机访问的端口(Web UI 的 80 端口和 Zabbix Server 的 10051 端口)映射出来。

部署 Zabbix:
在包含此 docker-compose.yaml 的目录 (/oldboyedu/docker-compose/02-zabbix/) 下,只需执行:

docker-compose up -d

Compose 会自动下载所需镜像,创建网络,并按依赖顺序启动所有容器。稍等片刻,即可通过浏览器访问 http://<宿主机IP> (因为我们将宿主机的 80 端口映射到了 Web UI 容器的 8080 端口) 来访问 Zabbix 的 Web 界面。

五、 总结

Docker Compose 是管理多容器应用程序的瑞士军刀。它通过简洁的 YAML 文件实现了对复杂应用架构的声明式定义,极大地简化了开发、测试和生产环境的部署与管理流程。

核心优势:

  • 简化管理: 使用简单命令即可管理整个应用的生命周期。
  • 环境一致性:确保开发、测试、生产环境的应用栈配置一致。
  • 快速部署与复现: 轻松分享和重建应用环境。
  • 服务编排: 定义服务依赖、网络连接和数据卷,实现容器间的有效协作。

掌握 Docker Compose 是现代 DevOps 工程师和开发人员的必备技能。通过它,你可以更高效、更可靠地构建和运行容器化应用。

posted on 2025-04-11 10:01  Leo-Yide  阅读(198)  评论(0)    收藏  举报