Skip to content

Docker 与 Docker Compose

Phase 07 — Engineering · 知识点 08–09:Docker · Docker Compose


1. 学习目标

完成本知识点后,你应该能够:

  • 理解 Docker 镜像、容器、Volume、Network 核心概念
  • 编写多阶段 Dockerfile 构建 Go 服务静态二进制镜像
  • 使用 Docker Compose 编排 Go、PostgreSQL、Redis
  • 通过环境变量向容器注入 Configuration
  • 配置健康检查(healthcheck)与依赖启动顺序
  • 实现 docker compose up 一键启动数字孪生后端完整依赖

2. 为什么需要

「在我机器上能跑」是协作和部署的大敌。Docker 把 Go 二进制、运行时依赖、PostgreSQL、Redis 打包成可复现环境,新成员无需手动安装数据库即可联调 Three.js 前端。

本路线不包含 Kubernetes——Docker Compose 足够支撑 Project 03 本地开发与中小型生产前验证。


3. 核心概念

3.1 Docker 核心

概念说明
Image只读模板,类似「类」
ContainerImage 的运行实例,类似「对象」
Dockerfile构建 Image 的脚本
Volume持久化数据(PostgreSQL 数据目录)
Network容器间通信(Compose 默认 bridge 网络)

3.2 Go 多阶段构建

Stage 1 (builder): golang:1.22-alpine → 编译静态二进制
Stage 2 (runtime):  alpine/scratch   → 仅复制二进制,镜像 ~20MB

3.3 Docker Compose

  • 单文件 docker-compose.yml 定义多服务
  • docker compose up -d 后台启动
  • 服务名即 DNS 主机名:postgres:5432redis:6379

4. 基础语法

4.1 Dockerfile(Go 服务)

dockerfile
# syntax=docker/dockerfile:1

FROM golang:1.22-alpine AS builder
WORKDIR /app
RUN apk add --no-cache git ca-certificates
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server

FROM alpine:3.19
RUN apk add --no-cache ca-certificates tzdata
WORKDIR /app
COPY --from=builder /server .
EXPOSE 8080
USER nobody
ENTRYPOINT ["./server"]

4.2 docker-compose.yml

yaml
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      APP_ENV: development
      HTTP_ADDR: ":8080"
      DATABASE_URL: postgres://twin:twin@postgres:5432/twin?sslmode=disable
      REDIS_ADDR: redis:6379
      LOG_LEVEL: debug
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 3

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: twin
      POSTGRES_PASSWORD: twin
      POSTGRES_DB: twin
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U twin -d twin"]
      interval: 5s
      timeout: 3s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

4.3 .dockerignore

.git
workspace/
exercises/
docs/
*.md
.env

减小 build context,加快构建。

4.4 常用命令

bash
docker compose build          # 构建镜像
docker compose up -d          # 后台启动
docker compose logs -f app    # 查看日志
docker compose ps             # 状态
docker compose down           # 停止并移除容器
docker compose down -v        # 同时删除 volume(慎用)

5. 代码解析

CGO_ENABLED=0:纯 Go 静态链接,runtime 镜像无需 glibc 依赖。

depends_on + condition: service_healthy:避免 app 在 PostgreSQL 未就绪时连接失败。

USER nobody:非 root 运行,降低容器逃逸风险。

环境变量 DATABASE_URL:主机名用服务名 postgres,不是 localhost(容器内 localhost 指向自身)。

Volumedocker compose down 不删 volume,数据保留;-v 才清空。


6. JavaScript / TypeScript 对比

概念前端Docker
环境隔离nvm / volta容器 OS 级隔离
依赖安装npm cigo mod download in build
多服务手动开多个终端Compose 一键
环境变量Vite .envCompose environment
部署产物静态文件 dist/Docker Image

前端 npm run dev 类比 docker compose up,但 Docker 包含后端依赖服务。


7. 常见错误

错误 1:DATABASE_URL 使用 localhost

Compose 网络内应使用服务名 postgres

错误 2:镜像过大

未使用多阶段构建,把源码和 Go toolchain 打进 runtime 镜像。

错误 3:未配置 healthcheck

app 启动时 DB 未就绪,连接失败后崩溃且不重启。

错误 4:把 .env secrets 写进 compose 并提交

生产用 secrets 或 CI 注入,compose 文件用 ${DATABASE_URL} 占位。

错误 5:开发时每次改代码都 rebuild

本地开发可只容器化 DB/Redis,Go 服务 go run 在宿主机;或使用 air 热重载 + 挂载 volume。


8. 实际应用

Project 03 Docker 交付

docker compose up -d
# → PostgreSQL 就绪
# → Redis 就绪
# → Go 服务 :8080
# → Three.js 前端连接 ws://localhost:8080/ws

验收

  • curl http://localhost:8080/health{"status":"ok"}
  • WebSocket 连接正常
  • 重启 docker compose restart app 数据不丢(PostgreSQL volume)

生产注意(Phase 08):

  • Compose 可用于单机生产,多机需其他方案(本路线不展开 K8s)
  • 镜像推送到 Registry(GHCR、Docker Hub)
  • 不在镜像内包含 .env

9. 深入理解

9.1 BuildKit 缓存

bash
DOCKER_BUILDKIT=1 docker compose build

go mod download 层缓存加速重复构建。

9.2 网络模式

  • ports: "8080:8080":宿主机访问
  • 容器间:服务名 DNS,无需暴露端口

9.3 WebSocket 与 Docker

无特殊配置;Nginx 反向代理时注意 Upgrade header(Phase 08)。


10. 练习

详细练习见 exercises/phase-07-engineering/03-docker-compose.md

Level 1 — 基础

练习 1.1:编写 Dockerfile,docker build -t twin-server . 成功。

练习 1.2:添加 .dockerignore,对比 build context 大小。

Level 2 — 应用

练习 2.1:Compose 添加 postgres + redis,app 连接成功。

练习 2.2:为 postgres 和 app 配置 healthcheck。

Level 3 — 综合

练习 3.1:环境变量切换 LOG_LEVEL=debuginfo,验证日志差异。

练习 3.2docker compose down -v 后重新 up,验证 DB 初始化迁移。

Level 4 — 项目实践

练习 4.1:Project 03 Phase 07 里程碑 — 完整 Compose + README 一键启动说明。


11. 学习检查

  1. 多阶段构建的优势是什么?
  2. Compose 内容器如何访问 PostgreSQL?
  3. Volume 与 bind mount 区别?
  4. 为什么 runtime 镜像用 CGO_ENABLED=0
  5. healthcheck 解决什么问题?

12. 下一步

已完成下一知识点关系
Docker · Docker ComposePhase 08 — Linux · SSH · Process · Port容器本地就绪 → 服务器部署

Phase 07 完成后,Project 03 具备测试与容器化能力。Phase 08 将学习在 Linux 服务器上部署 Go 二进制并通过 Nginx 对外提供 HTTPS/WSS。


学习导航

上一篇:测试与性能基准 · 对应练习 · 下一篇:Linux 运维基础