name: 容器化应用 description: | 使用 Docker、docker-compose 和 Helm 图表对应用程序进行容器化。 适用于为 Kubernetes 创建 Dockerfile、docker-compose 配置或 Helm 图表时。 包含 Docker 强化镜像(减少 95% 的 CVE)、多阶段构建以及 15 个以上经过实战检验的常见问题。
容器化应用
快速开始
- 首先运行影响分析(环境变量、网络拓扑、身份验证/CORS)
- 使用以下模式生成 Dockerfile
- 创建具有适当网络配置的 docker-compose.yml
- 打包为 Kubernetes 的 Helm 图表
Dockerfile 模式
FastAPI/Python(使用 uv 的多阶段构建)
# syntax=docker/dockerfile:1
FROM python:3.13-slim AS builder
WORKDIR /app
RUN pip install uv
COPY pyproject.toml .
RUN uv pip install --system --no-cache -r pyproject.toml
FROM python:3.13-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY . .
RUN useradd -u 1000 appuser && chown -R appuser /app
USER appuser
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Next.js(独立模式)
# syntax=docker/dockerfile:1
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_SSO_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_SSO_URL=$NEXT_PUBLIC_SSO_URL
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
docker-compose 模式
services:
web:
build:
context: ./web
args:
# BROWSER: 打包进 JS 包
- NEXT_PUBLIC_API_URL=http://localhost:8000
environment:
# SERVER: 在容器内运行时读取
- SERVER_API_URL=http://api:8000
ports:
- "3000:3000"
depends_on:
api:
condition: service_healthy
api:
build: ./api
environment:
- DATABASE_URL=${DATABASE_URL}
- CORS_ORIGINS=http://localhost:3000,http://web:3000
ports:
- "8000:8000"
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
Helm 图表结构
helm/myapp/
├── Chart.yaml
├── values.yaml
├── templates/
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ └── ingress.yaml
Chart.yaml
apiVersion: v2
name: myapp
version: 1.0.0
appVersion: "1.0.0"
values.yaml 模式
api:
replicaCount: 1
image:
repository: myapp/api
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8000
resources:
limits:
cpu: 500m
memory: 512Mi
Helm 命令
helm create mychart # 创建新图表
helm template . --debug # 渲染模板
helm install myapp ./chart # 安装
helm upgrade myapp ./chart # 升级
helm install myapp ./chart \
--set api.image.tag=v2.0.0 # 覆盖值
经过实战检验的常见问题(15+)
1. 浏览器端与服务器端 URL
问题: 浏览器在主机上运行,服务器在容器内运行
build:
args:
- NEXT_PUBLIC_API_URL=http://localhost:8000 # 浏览器端
environment:
- SERVER_API_URL=http://api:8000 # 服务器端
2. 健康检查 IPv6 问题
问题: wget http://localhost:3000 因 IPv6 失败
healthcheck:
test: ["CMD", "wget", "--spider", "http://127.0.0.1:3000/"] # 不要用 localhost!
3. MCP 服务器 421 错误请求
问题: FastMCP 拒绝 Docker 服务名称
transport_security = TransportSecuritySettings(
allowed_hosts=["127.0.0.1:*", "localhost:*", "mcp-server:*", "0.0.0.0:*"]
)
4. SQLModel 表未创建
问题: 在 create_all() 之前未导入模型
# 必须在 create_all() 之前导入
from .models import User, Task, Project # noqa: F401
SQLModel.metadata.create_all(engine)
5. 数据库迁移顺序
问题: Drizzle db:push 会删除不在模式中的表
解决方案: 启动 postgres → 运行 Drizzle → 然后启动 API
6. uv 网络超时
RUN UV_HTTP_TIMEOUT=120 uv pip install --system --no-cache -r pyproject.toml
7. 缺少语法指令
# syntax=docker/dockerfile:1 # 始终在第一行
FROM python:3.13-slim
8. 容器内的 localhost
服务器端使用 Docker 服务名称(api, web, sso),而不是 localhost
9. 身份验证来源
在构建之前将 Docker 服务名称添加到 trustedOrigins
10. 服务启动顺序
使用带有 condition: service_healthy 的 depends_on
11. 健康检查时机
对于需要时间启动的应用,使用 start_period(例如 40 秒)
12. pgAdmin 邮箱验证
使用有效的邮箱如 admin@example.com,而不是 .local 域名
13. Playwright 在依赖项中
将测试工具保留在 devDependencies 中(避免 300MB+ 的臃肿)
14. MCP 健康检查 406
通过 ASGI 中间件添加单独的 /health 端点
15. Helm 逗号解析
对于包含逗号的值,使用 values 文件而不是 --set
生产环境安全
Docker 强化镜像(推荐)
比社区镜像减少 95% 的 CVE。在 Apache 2.0 许可下免费使用。
# 之前:带有未知 CVE 的社区镜像
FROM python:3.12-slim
# 之后:Docker 强化镜像
FROM docker.io/docker/python:3.12-dhi
DHI 的五大支柱:
| 支柱 | 您将获得什么 |
|---|---|
| 最小攻击面 | 减少 98% CVE |
| 100% 完整 SBOM | SPDX/CycloneDX 格式 |
| SLSA 构建级别 3 | 已验证的来源 |
| OpenVEX | 机器可读的漏洞状态 |
| Cosign 签名 | 加密验证 |
验证签名:
cosign verify docker.io/docker/python:3.12-dhi
读取 SBOM:
docker sbom docker.io/docker/python:3.12-dhi
Trivy 扫描(CI/CD)
- name: 扫描漏洞
run: trivy image --severity HIGH,CRITICAL --exit-code 1 ${{ env.IMAGE }}
Distroless 镜像(替代方案)
# Python - 使用 gcr.io/distroless/python3-debian12
FROM gcr.io/distroless/python3-debian12
# 无 shell,无包管理器,默认以非 root 用户运行
多架构构建
- uses: docker/build-push-action@v5
with:
platforms: linux/amd64,linux/arm64 # 为两者构建
cache-from: type=gha
cache-to: type=gha,mode=max
BuildKit 密钥
# 在构建期间挂载密钥(永远不会存储在层中)
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN=$(cat /run/secrets/npm_token) npm install
完整模式请参阅 references/production-security.md。
验证
运行:python scripts/verify.py
相关技能
operating-k8s-local- 使用 Minikube 的本地 Kubernetesdeploying-cloud-k8s- 云 Kubernetes 部署scaffolding-fastapi-dapr- FastAPI 模式
参考资料
- references/production-security.md - Trivy、distroless、多架构、BuildKit 密钥