下载工作台
FastAPI 开发

Docker/K8s 交付与三框架选型结业

试读上半部分 · 解锁后可读全文

第 19 章 · Docker/K8s 交付与三框架选型结业

本章目标:为 svc-demo 编写多阶段 Dockerfile.dockerignore非 root 用户;使用 docker-compose.prod.yml 编排 api + worker + Nginx + PostgreSQL + Redis;理解 K8s 核心对象并阅读虚构 api.example.com YAML;全面对照 Django vs Flask vs FastAPI;回答面试框架选型;完成 19 章结业总结100 分进阶验收表(选修);说明与 xiaozi-cloud 衔接。

学时建议:6~8 小时(含 3 小时容器演练)

前置ch10 Celery 异步、ch17 连接池;ch18 可观测性。K8s 深度见 xiaozi-cloud


19.1 从「能跑」到「可交付」

源码 ──docker build──► registry.example.com/svc-demo:1.0.0 ──pull──► K8s / VM
                                                              api.example.com
交付物说明
Docker 镜像不可变制品,含依赖与代码
compose / K8s YAML进程拓扑与配置
.env.example文档化变量,不含密钥
虚构 svc-demoapi.example.comregistry.example.com严禁真实镜像地址、Kubeconfig、数据库密码。

19.2 多阶段 Dockerfile

svc-demo/Dockerfile

FROM python:3.12-slim AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends gcc libpq-dev \
    && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN python -m venv /opt/venv && /opt/venv/bin/pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim AS runtime
RUN apt-get update && apt-get install -y --no-install-recommends libpq5 curl \
    && rm -rf /var/lib/apt/lists/* \
    && groupadd --gid 1000 app && useradd --uid 1000 --gid app --create-home app
WORKDIR /app
ENV PATH="/opt/venv/bin:$PATH" PYTHONUNBUFFERED=1
COPY --from=builder /opt/venv /opt/venv
COPY --chown=app:app . .
USER app
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD curl -f http://127.0.0.1:8000/health || exit 1
CMD ["uvicorn", "svc_demo.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
实践原因
两阶段builder 装编译依赖,runtime 最小
USER app非 root,降权限
HEALTHCHECK编排器可重启不健康实例
--workers 2多进程利用 CPU(按核数调整)

构建与推送(虚构仓库):

docker build -t registry.example.com/svc-demo:1.0.0 .
docker push registry.example.com/svc-demo:1.0.0
docker run --rm -p 8000:8000 \
  -e DATABASE_URL=postgresql+asyncpg://svc_demo:dev@db:5432/svc_demo \
  -e SECRET_KEY=dev-only-not-for-prod \
  registry.example.com/svc-demo:1.0.0

生产可用 Gunicorn + UvicornWorker(选修):

CMD ["gunicorn", "svc_demo.main:app", "-k", "uvicorn.workers.UvicornWorker",
     "-b", "0.0.0.0:8000", "-w", "2", "--timeout", "60"]

19.3 .dockerignore

svc-demo/.dockerignore

.git
.venv
__pycache__
*.pyc
.pytest_cache
.mypy_cache
.env
.env.*
!.env.example
tests/
docs/
*.md
.dockerignore
Dockerfile
docker-compose*.yml

减小构建上下文,避免把 .env 打进镜像。


19.4 docker-compose.prod.yml

svc-demo/docker-compose.prod.yml

services:
  api:
    image: registry.example.com/svc-demo:1.0.0
    restart: unless-stopped
    env_file: .env.prod
    depends_on:
      db: {condition: service_healthy}
      redis: {condition: service_started}
    expose: ["8000"]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  worker:
    image: registry.example.com/svc-demo:1.0.0
    command: celery -A svc_demo.worker.celery_app worker -l info -c 2
    env_file: .env.prod
    depends_on: [api, redis, db]

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: svc_demo
      POSTGRES_USER: svc_demo
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes: [pg_data:/var/lib/postgresql/data]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U svc_demo"]
      interval: 10s

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes: [redis_data:/data]

  nginx:
    image: nginx:1.27-alpine
    ports: ["80:80", "443:443"]
    volumes:
      - ./deploy/nginx/api.example.com.conf:/etc/nginx/conf.d/default.conf:ro
      - ./deploy/certs:/etc/nginx/certs:ro
    depends_on: [api]

volumes:
  pg_data:
  redis_data:

.env.example(提交 Git,不含真实值):

DATABASE_URL=postgresql+asyncpg://svc_demo:CHANGE_ME@db:5432/svc_demo
REDIS_URL=redis://redis:6379/0
SECRET_KEY=CHANGE_ME
CELERY_BROKER_URL=redis://redis:6379/1

启动:

docker compose -f docker-compose.prod.yml up -d
docker compose -f docker-compose.prod.yml ps

Nginx 反代片段(deploy/nginx/api.example.com.conf):

upstream svc_demo {
    server api:8000;
}
server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://svc_demo;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    location /metrics {
        allow 10.0.0.0/8;
        deny all;
        proxy_pass http://svc_demo;
    }
}

19.5 Kubernetes YAML 导读

deploy/k8s/namespace.yaml

apiVersion: v1
kind: Namespace
metadata: {name: svc-demo-staging}

deploy/k8s/deployment.yaml

apiVersion: apps/v1

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。