跳转至

Docker 容器化与部署实战

基于 olad_data_ap 项目 infra/docker-compose.yml
来源:olad_data_ap/DEVELOPMENT.md
面试定位:证明你有现代化数据平台的完整部署和运维能力


〇、学习目标与面试关联

0.1 为什么要学习 Docker 部署?

维度 说明
面试价值 交易所 BI 岗位需要快速搭建数据环境,Docker 是基础能力
项目价值 olad_data_ap 用 Docker 编排 8 个组件,一键启动,降低环境配置成本
生产价值 证明你不仅会写 SQL/代码,还能搭建完整的数据平台基础设施

0.2 与交易所面试的直接关系

交易所场景:
  - 需要快速搭建测试环境(交易数据回放、风控测试)
  - 需要本地开发环境(ClickHouse/Spark/Airflow 调试)
  - 需要演示 Demo(Risk Dashboard、指标字典)
  - 需要隔离环境(不同项目/不同版本不冲突)

你的回答:
  "我用 Docker Compose 编排了 ClickHouse、PostgreSQL、Redis、
   Airflow、Prometheus/Grafana 等 8 个组件,通过 Makefile 封装
   了启动、停止、健康检查等命令。这让我能快速搭建完整的数据平台
   环境,也保证了开发、测试、演示环境的一致性。"

0.3 生产环境会用 Docker 吗?

会,而且很普遍,但有分层

场景 方案 为什么
开发环境 Docker Compose 快速启动、环境一致、方便调试
测试环境 Kubernetes(K8s)或 Docker Swarm 需要多实例、高可用
生产环境 Kubernetes(主流)或裸机 需要自动扩缩容、服务治理、灰度发布
数据平台 K8s + 专有组件(ClickHouse Operator) 数据组件有状态,需要特殊处理

0.4 Docker 的优劣势与生产痛点

✅ 优势

优势 说明 面试加分点
环境一致性 开发/测试/生产用同一镜像 "在我的笔记本上和在线上行为一致"
快速启动 秒级启动 vs VM 分钟级 "调试 Airflow DAG 可以秒级重启"
资源隔离 Namespace + Cgroup "ClickHouse 和 Airflow 互不影响"
版本管理 镜像 tag 管理版本 "可以随时回退到 v1.0 的 ClickHouse"
生态丰富 Docker Hub、Compose、Swarm "社区有大量现成镜像"

❌ 生产痛点与规避方案

痛点 场景 规避方案 面试回答示例
有状态组件管理难 ClickHouse/PG/Redis 数据持久化 用 Volume 或 Bind Mount;生产用 Operator "我用 ./data/clickhouse 绑定数据目录,但生产会改用 ClickHouse Operator 管理 StatefulSet"
网络性能损耗 高吞吐场景(如实时 Flink) 用 host 网络模式或 CNI 优化 "生产环境 Flink 会用 host 网络减少 NAT 开销"
日志收集复杂 容器日志分散、易丢失 用 Loki/ELK 集中采集 "我项目中用 Loki 采集所有容器日志,Grafana 统一查看"
监控指标缺失 容器内部指标看不到 用 Prometheus + exporters "每个服务都暴露 /metrics,Prometheus 定期抓取"
镜像体积大 Airflow 镜像 1GB+ 多阶段构建、Alpine 基础镜像 "我用 alpine 基础镜像,从 1.2GB 降到 350MB"
编排能力有限 Compose 不支持自动扩缩容 生产迁移到 K8s + Helm "开发用 Compose 快速验证,生产用 K8s 管理高可用"
安全隔离不足 容器共享内核 用 rootless 模式、安全策略 "生产会用非 root 用户运行容器,限制权限"

🎯 面试高频回答模板

"我们项目用 Docker Compose 做开发环境编排,
优点是快速启动、环境一致、方便调试。

但生产环境会迁移到 Kubernetes,因为:
1. 有状态组件(ClickHouse/PG)需要 Operator 管理
2. 需要自动扩缩容、健康检查、滚动更新
3. 需要更好的服务治理、灰度发布能力

Docker Compose 是开发阶段的利器,K8s 是生产阶段的标配。"

我的感悟
印象中生产使用场景:1. 调度期生成的实例使用容器来快速构建; 2. flink集群使用k8s快速部署
对于业务方来说是透明无感的


一、项目中的组件

1.1 基础设施组件

组件 作用 面试关联
ClickHouse OLAP 引擎,存储 ODS/DWD/DWS/ADS 核心,OLAP 选型
PostgreSQL 元数据存储(metric-svc / admin-svc) 字典/租户
Redis 缓存(看板/BFF/AI) 缓存策略
MinIO S3 兼容对象存储 备份/冷数据
Airflow 任务调度 DAG 编排
Prometheus 指标采集 可观测性
Grafana 监控面板 可视化
Loki 日志采集 日志聚合

1.2 编排架构

# infra/docker-compose.yml 核心配置
services:
  # ========== 数据层 ==========
  clickhouse:
    image: clickhouse/clickhouse-server:24.5
    ports:
      - "8123:8123"  # HTTP
      - "9000:9000"  # TCP(内部)
    volumes:
      - ./data/clickhouse:/var/lib/clickhouse
    environment:
      CLICKHOUSE_DB: ads
      CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ads_meta
      POSTGRES_USER: ads
      POSTGRES_PASSWORD: ads
    volumes:
      - ./data/postgres:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru

  # ========== 对象存储 ==========
  minio:
    image: minio/minio:latest
    ports:
      - "9000:9000"  # API
      - "9001:9001"  # Console
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: minio123
    command: server /data --console-address ":9001"

  # ========== 调度 ==========
  airflow-webserver:
    image: apache/airflow:2.8
    environment:
      AIRFLOW__CORE__EXECUTOR: LocalExecutor
      AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://ads:ads@postgres/ads_meta
    volumes:
      - ./dags:/opt/airflow/dags
    depends_on:
      - postgres

  # ========== 可观测性 ==========
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./infra/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    volumes:
      - ./infra/grafana/provisioning:/etc/grafana/provisioning

  loki:
    image: grafana/loki:latest

二、核心概念

2.1 Docker vs Docker Compose

Docker:单容器管理
- docker run -d redis:7        # 运行一个容器
- docker ps                    # 查看运行中的容器
- docker logs <container_id>   # 查看日志
- docker exec -it <id> sh     # 进入容器

Docker Compose:多容器编排
- docker-compose up -d         # 启动所有服务
- docker-compose ps           # 查看所有服务状态
- docker-compose logs -f      # 实时日志
- docker-compose down         # 停止所有服务
- docker-compose up --build   # 重新构建镜像

2.2 常用命令

# 项目中 Makefile 封装的命令
make up           # docker-compose up -d
make ps          # docker-compose ps
make logs        # docker-compose logs -f
make down        # docker-compose down
make clean       # docker-compose down -v(删除数据卷)

# 常见问题排查
docker logs <service_name>     # 查看服务日志
docker exec -it <service_name> clickhouse-client  # 进 CH 调试
docker stats                  # 查看资源占用
docker network inspect olad_data_ap_default  # 查看网络

三、面试高频问题

Q1: Docker 容器和虚拟机的区别?

答:
| 维度 | VM | Docker 容器 |
|------|-----|------------|
| 启动时间 | 分钟级 | 秒级 |
| 资源占用 | 完整 OS,GB 级 | 共享内核,MB 级 |
| 隔离性 | 完全隔离 | 共享内核,进程级隔离 |
| 可移植性 | 依赖 Hypervisor | 镜像,到处运行 |
| 性能 | 有损耗 | 接近原生 |

面试加分点:
- 容器使用 Linux Namespace + Cgroup 实现隔离
- 镜像是分层叠加(UnionFS / OverlayFS)
- Docker Hub 生态丰富

Q2: Docker 网络模式?

答:四种模式
1. bridge(默认):容器间通信,与宿主机隔离
2. host:容器共享宿主机网络栈
3. overlay:跨主机容器通信(Swarm)
4. none:禁用网络

项目中用:
- 默认 bridge 模式
- 通过 networks 指定自定义网络
- 外部访问通过 ports 映射

Q3: Docker 数据持久化?

答:两种方式
1. Volume:Docker 管理的数据卷
   - docker volume create mydata
   - 适合数据迁移和备份

2. Bind Mount:绑定宿主机目录
   - -v /host/path:/container/path
   - 适合开发环境,文件实时同步

项目中用:
- ./data/clickhouse 绑定到 /var/lib/clickhouse
- ./dags 绑定到 /opt/airflow/dags

Q4: 如何排查容器启动失败?

步骤:
1. docker-compose ps 查看状态
2. docker-compose logs <service> 查看错误日志
3. docker inspect <container_id> 查看详细信息

常见问题:
- 端口冲突:Bind for :::9000 failed
  → 修改 CH_TCP_PORT 或停掉 MinIO
- 权限问题:Permission denied
  → chown -R 101:101 /data
- 依赖未就绪:Airflow init 失败
  → 等 PG 就绪后重起,或加 depends_on

四、项目实践 Checklist

  • 理解 docker-compose 服务的依赖关系
  • 能用 docker-compose up/down 管理基础设施
  • 能排查常见启动问题(端口/权限/依赖)
  • 理解 Volume 和 Bind Mount 的区别
  • 能用 docker exec 进入容器调试

相关文档: - ClickHouse 深度解析 - Redis 缓存策略(待补充) - olad_data_ap DEVELOPMENT.md