Docker Compose 入门:一条命令启动多服务

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。

在上一篇文章的末尾,我留了一个问题:每次启动 Flask + Redis 应用都要敲七八条命令,太累了。有没有更优雅的方式?

有。这就是我们今天的主角------Docker Compose

如果你跟着第 10 篇亲手敲过那几十条命令,一定能感受到手动管理的痛苦:要先创建网络、创建数据卷、启动 Redis、等待 Redis 就绪、启动 Flask......顺序不能错,参数不能漏,换一台机器又得重来一遍。Docker Compose 的目标就是把这些步骤写进一个 YAML 文件,然后一条命令搞定一切 。这篇就来带你入门 Compose,把 Flask + Redis 计数器应用的启动过程从"手动敲 8 条命令"变成"一条 docker compose up"。

一、Compose 是什么?解决什么问题?

Docker Compose 是 Docker 官方推出的多容器应用编排工具,核心价值就是用声明式的 YAML 文件描述整个应用栈,包括服务、网络、数据卷的配置,然后通过一条命令统一管理所有服务的生命周期。

看一下我们第 10 篇手动操作的痛点,以及 Compose 是如何一一解决的:

二、V1 vs V2 vs V3:我该用哪个?

在开始写配置文件之前,有必要弄清楚版本号的问题。

Docker Compose 文件格式经历了多次演变:V1 格式(docker-compose.yml,无 version 字段)是早期版本,已经彻底废弃;V2 格式引入了 version: '2.x',支持命名卷和网络;V3 格式(version: '3.x')增加了 Swarm 部署相关配置。

但现在(2024 年起)Docker 官方已弃用 version 字段。使用 docker compose(V2 命令,中间是空格,不是横杠)时,直接编写不带 version 的 YAML 文件即可,Docker 会自动使用 Compose Specification 规范解析。如果你看到一些教程还在使用 version: '3',那是历史遗留写法,功能上仍然可用,但官方推荐不再写 version

本系列全部采用最新的 Compose Specification 格式(无 version 字段),命令使用 docker compose(空格版)

三、编写第一个 docker-compose.yml

把第 10 篇的启动流程"翻译"成 Compose 文件。在项目根目录下新建 docker-compose.yml

bash 复制代码
# ============================================================
# Flask + Redis 计数器应用 ------ Docker Compose 配置文件
# 系列贯穿案例
# ============================================================

services:
  # ---- Redis 服务 ----
  redis:
    image: redis:alpine
    container_name: redis
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - app-net
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 5s

  # ---- Flask 应用服务 ----
  flask-app:
    image: flask-redis-counter:2.0
    # 如果镜像不在本地,可以改为 build: . 来从 Dockerfile 构建
    container_name: flask-app
    restart: unless-stopped
    ports:
      - "5000:5000"
    volumes:
      - flask-logs:/app/logs
    networks:
      - app-net
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 3s
      start_period: 5s
      retries: 3

# ---- 数据卷 ----
volumes:
  redis-data:
  flask-logs:

# ---- 网络 ----
networks:
  app-net:
    driver: bridge

3.1 文件结构拆解

Compose 文件包含三个顶级元素:

services :定义应用栈中每个服务的配置。每个服务相当于一个 docker run 命令的完整参数集合。当前定义了两个服务------redisflask-app。在 Compose 管理的网络中,服务名(redisflask-app)会自动作为 DNS 记录,其他服务可以通过服务名直接访问。这就是为什么 app.py 里写的 host='redis' 能直接工作------Compose 自动创建了 DNS 解析。

volumes :声明命名卷。与手动执行 docker volume create 创建的效果完全一致,但由 Compose 统一管理生命周期。docker compose down 时默认不会删除 volumes(防止误删数据),如需删除需加 -v 参数。

networks :声明网络。driver: bridge 表示创建自定义 bridge 网络,与第 8 篇手动执行 docker network create app-net 的效果完全一致。

3.2 关键指令说明

3.3 depends_on 的两种写法

depends_on 有两种用法,效果差异很大:

简单写法(仅控制启动顺序)

这种写法只保证 redis 容器先启动,但不等待 Redis 服务就绪------redis 容器可能处于 "Up" 状态但 Redis 进程还在加载数据,此时 Flask 连接 Redis 会失败。

条件写法(等待健康检查通过)

bash 复制代码
depends_on:
  redis:
    condition: service_healthy

这是我们现在用的写法:condition: service_healthy 表示不仅要等 redis 容器启动,还要等它的健康检查通过redis-cli ping 返回 PONG),才会启动 flask-app。这个 service_healthy 条件引入了 Compose v2.1+ 规范,到 Compose v3 曾被标记为 deprecated,但在最新的 Compose Specification 中又正式回归。使用 docker compose 命令即可正常使用,完全不需要 version 字段。

四、核心命令:从 up 到 down

4.1 docker compose up:一键启动

bash 复制代码
# 前台启动(可以看到所有服务的日志交错输出)
docker compose up

# 后台启动(推荐日常使用)
docker compose up -d

输出:

bash 复制代码
[+] Running 3/3
 ✔ Network flask-redis-counter_app-net    Created    0.1s
 ✔ Volume "flask-redis-counter_redis-data"  Created    0.0s
 ✔ Volume "flask-redis-counter_flask-logs"  Created    0.0s
 ✔ Container redis                         Started    0.5s
 ✔ Container flask-app                     Started    1.2s

注意两个细节:第一,网络和卷的名称会自动带上项目名(默认是当前目录名,这里是 flask-redis-counter)作为前缀,避免不同项目之间的资源名称冲突。第二,docker compose up -d 仅启动服务,不会重新构建镜像。如果你修改了 Dockerfile 或代码,需要先 docker compose buildup,或者直接用 docker compose up --build -d

4.2 查看服务状态

输出:

bash 复制代码
NAME        IMAGE                        COMMAND                  SERVICE     STATUS                    PORTS
flask-app   flask-redis-counter:2.0     "python app.py"          flask-app   running (healthy)         0.0.0.0:5000->5000/tcp
redis       redis:alpine                "docker-entrypoint.s..."   redis       running (healthy)         6379/tcp

注意两点:docker compose ps 只会显示当前项目 的容器(根据 docker-compose.yml 所在目录识别项目),不会混入宿主机上其他 Docker 容器;STATUS 列标注了 (healthy),说明两个服务的 HEALTHCHECK 都已通过。

4.3 查看日志

bash 复制代码
# 查看所有服务的日志
docker compose logs

# 实时跟踪日志
docker compose logs -f

# 只看特定服务
docker compose logs flask-app

# 看最后 50 行
docker compose logs --tail=50 flask-app

docker compose logsdocker logs 最大的区别在于:前者会聚合所有服务的日志,并在每条日志前标注服务名,对于排查跨服务的调用链问题非常方便。

4.4 扩容服务

这是手动模式最难做到的事情------Compose 一条命令搞定

bash 复制代码
# 将 Flask 服务扩容到 3 个实例
docker compose up -d --scale flask-app=3
bash 复制代码
[+] Running 3/3
 ✔ Container redis     Running    0.0s
 ✔ Container flask-app Started    0.3s
 ✔ Container flask-app-2 Started  0.4s
 ✔ Container flask-app-3 Started  0.4s

--scale 参数在 docker compose 中仅用于临时一次性扩容 ,不会持久化到配置文件。下次执行 docker compose up -d 时,副本数会恢复为默认的 1 个。如果需要长期使用多个副本,建议在 Compose 文件中使用 deploy.replicas(需 Swarm 模式),或直接用 K8s 的 Deployment 管理。

4.5 停止与清理

bash 复制代码
# 停止所有服务(不删除容器、网络、卷)
docker compose stop

# 启动已停止的服务
docker compose start

# 停止并删除容器(不删除网络和卷)
docker compose down

# 停止并删除容器、网络(保留卷,防止误删数据)
docker compose down --volumes
# 或简写
docker compose down -v

注意docker compose down 默认不会删除 volumes ,这是出于数据安全的考虑。如果你确定要彻底清理包括数据在内的所有资源,必须显式加 -v

五、完整验证流程

bash 复制代码
# 1. 确认目录结构
ls
# app.py  docker-compose.yml  Dockerfile  requirements.txt  .dockerignore

# 2. 启动应用栈
docker compose up -d

# 3. 查看状态
docker compose ps

# 4. 测试功能
curl http://localhost:5000
# Hello World! I have been seen 1 times.
curl http://localhost:5000
# Hello World! I have been seen 2 times.

# 5. 测试健康检查
curl http://localhost:5000/health
# {"status":"ok"}

# 6. 查看聚合日志
docker compose logs --tail=20

# 7. 停止服务
docker compose down

现在,整个 Flask + Redis 应用栈的启动从第 10 篇的"手动敲 8 条命令"变成了:

一条命令,从启动 Redis、等待就绪、启动 Flask,到创建网络和数据卷,全部自动完成。

六、V1 vs V2 命令对比

Docker Compose 有两个命令版本,如果你在网上看教程,可能会遇到混用的情况。以下是区别:

如果你之前用过 docker-compose(带横杠),现在统一换为 docker compose(空格)。两者语法 99% 兼容,但 V2 在性能和功能上更优。

七、本篇总结

Docker Compose 解决的核心问题就是------把多容器应用从手动管理变成声明式管理

  • 声明式配置docker-compose.yml 一站式定义服务、网络、卷,可纳入 Git 管理

  • 一键启停docker compose up -ddocker compose down,告别冗长的手动命令

  • 健康检查驱动的启动顺序depends_on + condition: service_healthy,不再需要 sleep

  • 服务扩容--scale 参数快速测试多副本场景

  • 聚合日志:一个命令查看整个应用栈的日志,跨服务排错效率大幅提升

📝 本篇暂不要求实操 :你可以先阅读本文理解 Compose 的概念和基本命令。下一篇文章------第 12 篇:Docker Compose 文件详解:服务、网络与卷,我们将深入拆解 Compose 文件的每一个配置项,并带你亲手完成完整的部署演练。届时请务必跟着操作一遍。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

相关推荐
“码”力全开15 小时前
【架构深析】基于 Docker 与边缘计算的 AI 视频管理平台:从 GB28181/RTSP 统一接入到源码交付的闭环演进
人工智能·docker·架构
Cat_Rocky15 小时前
CICD-DevOps简单学习
运维·学习·devops
IT策士15 小时前
Docker Compose 文件详解:服务、网络与卷
网络·docker·容器
陈海明hack15 小时前
AI的变革下,AI基础设施工程师的技术核心和培养方案(原运维架构师)
运维·人工智能
wanhengidc15 小时前
服务器如何防范病毒攻击
运维·服务器·游戏
IT策士15 小时前
Docker 网络入门:桥接、自定义与主机网络
网络·docker·容器
ylatin15 小时前
frp使用 网络
运维·服务器·网络
会Tk矩阵群控的小木15 小时前
深入解析tk矩阵系统ADB实时投屏与多设备控制实现
运维·线性代数·adb·矩阵·个人开发
^ω^。15 小时前
K8s知识
云原生·容器·kubernetes