第七章

docker-compose:一条命令拉起全家桶

第六层 · 编排/多容器 一条命令拉起整个书店系统

一、五个容器,二十条命令,谁来记?

小陈把直播带货模块容器化之后,部署流程是这样的:

# 每次部署要敲的命令(节选):
docker network create livestream-net
docker volume create ls-db-data
docker volume create ls-upload
docker run -d --network livestream-net -v ls-db-data:/var/lib/mysql --name ls-db mysql:8.0
docker run -d --network livestream-net -v ls-upload:/upload --name ls-upload upload:v1
docker run -d --network livestream-net -p 8000:8000 --name ls-api api:v1
docker run -d --network livestream-net -p 80:8080 --name ls-web web:v1
docker run -d --network livestream-net --name ls-cache redis:7
# ……还有环境变量、重启策略、资源限制……全都得记得清清楚楚

小陈瘫在椅子上:"师傅,这哪是部署,这是背口诀啊。换个新人来,光这些参数就够他记三天。"

老周:"所以有了 docker-compose——把'整个系统怎么部署'写成一个配置文件,一条命令,全部搞定。"


二、docker-compose.yml:系统的"部署说明书"

老周带小陈写了一个 docker-compose.yml

# docker-compose.yml —— 云间书店直播带货模块
version: "3.8"

services:                        # 定义"有哪些服务"(= 容器)
  db:                            # 数据库
    image: mysql:8.0
    container_name: ls-db
    environment:                 # 环境变量(代替 -e)
      MYSQL_ROOT_PASSWORD: YunJian2026
      MYSQL_DATABASE: livestream
    volumes:                     # 数据卷(代替 -v)
      - db-data:/var/lib/mysql
    restart: always              # 重启策略(代替 --restart)

  cache:                         # 缓存
    image: redis:7
    container_name: ls-cache
    restart: always

  api:                           # 后端 API
    build: ./api                 # 用 Dockerfile 构建(代替 docker build)
    container_name: ls-api
    environment:
      DB_HOST: db                # 直接写服务名!compose 自动 DNS
      DB_PASSWORD: YunJian2026
    depends_on:                  # 依赖:先启动 db 再启动 api
      - db
    restart: always

  web:                           # 前端
    build: ./web
    container_name: ls-web
    ports:                       # 端口映射(代替 -p)
      - "80:8080"
    depends_on:
      - api
    restart: always

volumes:                         # 声明数据卷(代替 docker volume create)
  db-data:

"看到了吗?之前所有 docker run 的参数,全部变成了配置文件里的一行行声明。 这个文件就是整个系统的'部署说明书'——团队任何人拿到它,都能一键部署出完全一样的系统。"


三、一条命令搞定一切

# 启动全家桶(核心命令)
docker compose up -d

# 其他常用命令
docker compose ps               # 看所有服务状态
docker compose logs -f api      # 看某个服务的日志
docker compose down             # 停掉所有服务(容器删除)
docker compose down -v          # 连数据卷一起删(数据也没了!慎用)
docker compose restart api      # 重启某个服务
docker compose exec api bash    # 进某个服务
docker compose pull             # 拉取最新镜像

# 更新:改了代码,重新构建并启动
docker compose up -d --build

"docker compose up -d 就是云间书店的标准部署命令。 部署从'背二十条命令'变成'一条命令 + 一个配置文件'——而且这个文件可以放进 Git 版本管理,谁改了什么一目了然。"


四、compose 三件套:服务、网络、卷

"compose 文件里最核心的三个顶级配置:services、networks、volumes。"老周说:

services(服务)  :定义"有哪些容器",每个服务就是一个容器
networks(网络)  :定义"容器之间的网络"(默认自动建一个)
volumes(卷)    :定义"数据卷"(容器之间共享/持久化)

关键机制:
  ① 自动网络:compose 默认创建一个网络,
     所有服务都在里面,直接用"服务名"互访(不用手动建网)
  ② 自动卷:声明在 volumes 里的卷,Docker 自动创建
  ③ 依赖顺序:depends_on 控制启动顺序
     (先 db,再 api,再 web)

对比手动 docker run:
  手动:网络、卷、启动顺序、环境变量……全靠人脑记
  compose:全部写进文件,可版本管理、可审阅、可复用

"compose 的价值不是'少敲几条命令',是'把部署逻辑变成代码'——可复现、可审计、可交接。这就是前面说的'环境即代码'的完整落地。"


五、环境变量与 .env:配置和代码分离

"还有一个生产必备技巧:环境变量分离。"老周说,"密码写死在 compose 文件里,要是文件传到 Git 上,密码就泄露了。"

# docker-compose.yml 里用变量占位
environment:
  MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}   # 从 .env 读取
# .env 文件(不提交到 Git!)
MYSQL_PASSWORD=YunJian2026Secret

# 或者部署时用环境变量
export MYSQL_PASSWORD=YunJian2026Secret
docker compose up -d
配置管理原则:
  - 代码、镜像可以进 Git,密码、密钥绝对不进 Git
  - 用 .env 文件(加 .gitignore)+ 部署机环境变量
  - 敏感信息还可以用 Docker Secret(Swarm/K8s 场景)

"记住:配置文件里永远不要写死密码。 这是安全底线,也是专业和业余的分水岭。"


六、云间书店的完整 compose 架构

老周最后给小陈看了直播带货模块的完整架构:

docker compose up -d 之后,云间书店得到:

  ┌─────────────────────────────────────────┐
  │  外部访问 → 宿主机:80                      │
  │  │                                       │
  │  ▼                                       │
  │  ls-web(前端, 80:8080)                  │
  │  │ 调用                                 │
  │  ▼                                       │
  │  ls-api(后端 API)                       │
  │  ├──→ ls-db(MySQL, 数据卷 db-data)       │
  │  └──→ ls-cache(Redis)                  │
  │  ls-upload(文件上传, 卷 ls-upload)       │
  │  (都在同一个自动网络里,用服务名互访)       │
  └─────────────────────────────────────────┘

  部署 = git pull + docker compose up -d --build
  回滚 = docker compose down + 用旧镜像 up

"师傅,compose 已经很好用了,为什么还要学 Kubernetes?"小陈问。

"问到点子上了。"老周说,"compose 适合'单台机器上的多容器编排'。但云间书店以后要多台服务器、容器要跨机器调度、流量大了要自动扩容、一台机器挂了容器要自动迁移……compose 管不了跨机器的'集群'。 那就是第九章 Kubernetes 的领域。不过在那之前,还有一件要紧事——镜像仓库。你的镜像,总不能只存在自己电脑上吧?"

✌ 语言