写给懒猫微服玩家的容器小书Docker篇(五):《多容器交响曲:Docker Compose 上场》

忘机山人

发布于378天前
博客图片修整中,看不了可以先搜索公众号“忘机山人”看。
> 一直想写一本容器小书,真好懒猫基本都做了容器化,所以把这部分分享出来。不同的是,懒猫微服中使用pg-docker来替代docker命令,使用dockge来执行docker-compose。以下讲解以标准docker为主,这样子既学会了docker知识,也能够在懒猫微服上启动Docker服务。



# 《多容器交响曲:Docker Compose 上场》讲的是使用 Docker Compose 统一编排多容器服务,理解 YAML 配置结构、服务依赖、网络、挂载、构建策略、变量管理、Compose vs K8s 初探等

------

### 🎼 开篇:服务之间的管弦乐团

随着项目日益复杂,小李的服务已经不再是一个容器就能承载的了。

前端、后端、数据库、缓存、日志系统……像一个交响乐团,需要统一调度、和谐配合。

老周递给他一个新的工具:“**Docker Compose**——它是你的指挥棒。”

------

## 🎻 第一节:什么是 Docker Compose?

老周解释:

> “Docker Compose 是 Docker 的多容器编排工具,用一份 `docker-compose.yml` 文件,就能同时启动、停止、构建多个服务。”

Compose 帮你解决:

- 多个服务启动顺序
- 多容器共享网络
- 统一管理环境变量
- 配置简洁、开发者友好
- 跨平台部署一致

------

## 📄 第二节:写出你的第一个 `docker-compose.yml`

小李的项目结构如下:

```
myapp/
├── backend/      # Flask 应用
│   ├── app.py
│   └── Dockerfile
├── frontend/     # 静态页面
│   ├── index.html
│   └── Dockerfile
└── docker-compose.yml
```

### `docker-compose.yml` 示例:

```yaml
version: '3.9'

services:
  backend:
    build: ./backend
    ports:
      - "5000:5000"
    volumes:
      - ./backend:/app
    environment:
      - DB_HOST=db
    depends_on:
      - db

  frontend:
    build: ./frontend
    ports:
      - "3000:80"

  db:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=mydb
    volumes:
      - dbdata:/var/lib/mysql

volumes:
  dbdata:
```

> 🔧 每个 `service` 就是一个容器定义,Compose 会为它们创建默认网络,自动 DNS 互通。

------

## 🧪 第三节:Compose 命令实战速查

小李在项目目录下运行:

```bash
docker-compose up -d
```

后台启动所有服务!

其他常用命令:

| 操作                | 命令                              |
| ------------------- | --------------------------------- |
| 构建镜像            | `docker-compose build`            |
| 后台启动            | `docker-compose up -d`            |
| 前台启动 + 日志输出 | `docker-compose up`               |
| 停止服务            | `docker-compose down`             |
| 查看容器日志        | `docker-compose logs [服务名]`    |
| 重启某个服务        | `docker-compose restart 服务名`   |
| 进入某个容器        | `docker-compose exec 服务名 bash` |

------

## 📦 第四节:Compose 的网络与数据共享机制

老周介绍:

> “Compose 默认创建一个网络,**所有服务能通过服务名互相访问**。”

在上面的例子中:

- `backend` 容器可以用 `db:3306` 连接 MySQL
- `frontend` 可通过 `backend:5000` 访问后端 API

> 小李不再需要手动 `docker network create` 和 `--network` 参数,Compose 一切自动打通。

### Volume 的挂载:

Compose 中的 volume 显式声明(如 `dbdata:`)会自动创建、管理。

支持:

```yaml
volumes:
  - ./data:/data                # Bind mount
  - myvolume:/data              # Named volume
  - /custom/path:/data:ro       # 带权限控制
```

------

## 🌐 第五节:使用 `.env` 管理配置变量

Compose 支持使用 `.env` 文件集中管理变量:

`.env` 文件:

```env
DB_PASSWORD=123456
DB_NAME=mydb
```

Compose 文件中使用方式:

```yaml
environment:
  - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
  - MYSQL_DATABASE=${DB_NAME}
```

> 🚀 配合 CI/CD 时 `.env` 可由流水线动态生成,便于多环境切换(dev/stage/prod)。

------

## 🧬 第六节:高级配置技巧

### 1. 统一重启策略:

```yaml
restart: unless-stopped
```

确保服务宕机时能自动重启。

------

### 2. 多阶段构建支持:

```yaml
build:
  context: ./backend
  dockerfile: Dockerfile.prod
```

可指定构建路径、Dockerfile 文件、构建参数等。

------

### 3. Healthcheck 健康检查:

```yaml
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
  interval: 30s
  timeout: 10s
  retries: 3
```

------

## 🆚 第七节:Docker Compose vs Kubernetes 简析

| 特性          | Compose          | Kubernetes        |
| ------------- | ---------------- | ----------------- |
| 启动容器      | 简单             | 标准化            |
| 配置语言      | YAML             | YAML              |
| 网络          | 自动共享         | 需显式配置        |
| 存储          | Volume           | PVC + SC          |
| 服务发现      | 服务名互通       | DNS/ClusterIP     |
| 用途          | 本地开发 / CI    | 集群部署 / 云原生 |
| 高可用 / 伸缩 | ❌                | ✅ 内建            |
| 社区生态      | 中小项目广泛使用 | 大型平台标准方案  |

> 小李理解了:Compose 是“轻量乐队指挥”,K8s 是“交响级 AI 指挥系统”。

------

## 🔁 第八节:Compose + CI/CD 集成发布

小李将 Compose 整合进 GitLab CI 流程:

`.gitlab-ci.yml` 示例:

```yaml
services:
  - docker:dind

stages:
  - build
  - deploy

build:
  stage: build
  script:
    - docker-compose build

deploy:
  stage: deploy
  script:
    - docker-compose up -d
```

CI 构建完镜像后,直接用 Compose 部署,既省事又稳定。

------

## 🧠 小李 Compose 使用技巧总结

| 目标       | 技巧                                  |
| ---------- | ------------------------------------- |
| 服务隔离   | 每个项目单独一个 Compose 文件         |
| 共享网络   | 不用写 `network`,服务名即 DNS        |
| 跨环境配置 | 使用 `.env` 动态切换变量              |
| 状态排查   | `docker-compose logs` / `ps` / `exec` |
| 多环境文件 | 使用 `docker-compose.override.yml`    |
| CI/CD 联动 | 编排命令嵌入流水线任务中              |

------

## 🎬 尾声:指挥容器交响曲的时刻

当小李敲下 `docker-compose up` 的回车键,前端、后端、数据库同时启动,日志齐鸣,服务稳定运行。

> “这就是我梦想的微服务协奏曲啊。”

老周拍了拍他肩膀:

> “你已经能用 Compose 驾驭服务之海,下一步,是把它们部署上云、扩展弹性、自动滚动升级。”

小李点头,望向远方的集群编排系统——Kubernetes,眼中闪着新的渴望。







好!那我们就在**第五章《多容器交响曲》**中,继续深入补充这四大实战技能:

------

## 🧩 补充一:Compose 的多环境部署实践(开发、测试、生产)

小李希望同一套服务,在开发、测试、生产环境下分别使用不同的配置,比如:

- 数据库密码不同
- 是否挂载本地代码
- 是否启用调试模式

老周教他使用 Compose 的**多文件配置机制**:

------

### ✅ 方案一:使用 `docker-compose.override.yml`

Docker Compose 默认会**自动加载 `docker-compose.override.yml`** 并与主文件合并。

#### 文件结构:

```
docker-compose.yml
docker-compose.override.yml
.env.dev
.env.prod
```

#### 主配置(docker-compose.yml):

```yaml
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - ENV_MODE=${MODE}
```

#### 开发环境覆盖文件(docker-compose.override.yml):

```yaml
services:
  web:
    volumes:
      - ./src:/app/src
    environment:
      - DEBUG=true
```

运行:

```bash
MODE=development docker-compose up
```

------

### ✅ 方案二:按环境拆分多个 Compose 文件

适合 CI/CD 或部署多个 stage。

#### 示例:

- `docker-compose.dev.yml`
- `docker-compose.prod.yml`

运行:

```bash
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
```

多个 `-f` 会按顺序合并,后面覆盖前面。

> 📦 建议主文件写“公共配置”,子文件按环境细化。

------

## 🎯 补充二:优化服务依赖启动顺序

小李发现,即使写了 `depends_on`,后端有时候也连不上数据库。

老周摇头说:

> “`depends_on` 只是控制启动**顺序**,**不是等服务就绪**。数据库可能还没监听端口就已被标记为 'up'。”

------

### ✅ 正确姿势:服务内设置“等待就绪”

比如 Flask 等数据库:

```bash
#!/bin/bash
until nc -z db 3306; do
  echo "Waiting for db..."
  sleep 1
done

python app.py
```

或者使用工具包如 [`wait-for-it.sh`](https://github.com/vishnubob/wait-for-it):

```dockerfile
COPY wait-for-it.sh /wait-for-it.sh
ENTRYPOINT ["/wait-for-it.sh", "db:3306", "--", "python", "app.py"]
```

> 🩺 推荐结合容器健康检查,判断服务是否真正 ready。

------

## 🛠 补充三:Docker Compose V1 ➜ V2 迁移技巧

小李的 CI 工具用的是 Compose v1,项目准备升级。

老周提醒:

> “Docker Compose v2 使用的是 `docker compose`(空格),而非 `docker-compose`(短横线)。”

------

### ✅ 主要变化:

| 项目     | v1 (`docker-compose`) | v2 (`docker compose`) |
| -------- | --------------------- | --------------------- |
| 命令格式 | `docker-compose up`   | `docker compose up`   |
| 安装方式 | 独立二进制            | 集成于 Docker CLI     |
| 文件格式 | `v2`, `v3`            | 推荐统一 `v3.9`       |

------

### ✅ 迁移建议:

- 删除旧的 `docker-compose` 二进制
- 使用 `docker compose` CLI
- 更新脚本、CI 工具调用方式
- 移除 legacy 字段(如 `links`)
- 检查 `.env` 是否兼容(v2 更严格)

------

## ☸️ 补充四:Compose 与 Helm 的映射关系对照

当小李进入 Kubernetes 世界,他问老周:

> “Compose 文件和 K8s 的 YAML 有啥对应关系?”

老周说:“很好理解,Compose 是开发者的 K8s 简化版本。”

------

### 对照表:

| Compose              | Kubernetes                           |
| -------------------- | ------------------------------------ |
| `services:`          | `Deployment + Pod`                   |
| `volumes:`           | `PersistentVolumeClaim`              |
| `ports:`             | `Service`(NodePort / ClusterIP)    |
| `depends_on:`        | `initContainers` 或 readinessProbe   |
| `.env`               | ConfigMap / Secret                   |
| `docker-compose.yml` | Helm Chart (values.yaml + templates) |

------

### 示例:Compose 转 Helm 构思

#### Compose 配置:

```yaml
services:
  web:
    image: myapp:latest
    ports:
      - "8080:80"
    environment:
      - DEBUG=true
```

#### Helm `values.yaml`:

```yaml
image:
  repository: myapp
  tag: latest

env:
  - name: DEBUG
    value: "true"

service:
  port: 8080
  targetPort: 80
```

#### Helm `deployment.yaml`(模板):

```yaml
containers:
  - name: web
    image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
    env:
      {{- range .Values.env }}
      - name: {{ .name }}
        value: {{ .value }}
      {{- end }}
```

> ✅ 小李意识到,Helm 是“模板化 + 分层管理”的 Compose 超集,是云原生部署的标准组件管理器。

------

## 🎬 尾声:Compose 是微服务上云的跳板

小李已经用 Docker Compose 实现了:

- 开发环境热更新
- 测试环境集成数据库
- 生产环境独立配置
- CI/CD 自动部署服务
- 为 Kubernetes 迁移打下基础

他明白了:

> “Compose 就像舞台排练,Kubernetes 才是真正的大型音乐厅。但有了排练,登台才不会慌。”

评论

0

暂无评论

说点什么呢~
收藏
2
0
0