返回首页
⚙️ 后端 / 架构
Docker 多阶段构建最佳实践:从 1GB 到 100MB
Docker 多阶段构建可以把镜像从 1GB 缩小到 100MB。本文演示 6 个真实案例,包括 Node.js / Go / Rust。
Docker · 多阶段构建 · 镜像优化 · 后端
📰
今日技术简讯
📰 技术简讯 · 2026-06-28
今日聚合 6 条热门技术内容(周日)。
🤖 AI / LLM
1. GPT-5.5 推出 Realtime Vision
- 链接:https://platform.openai.com/docs/realtime-vision
- 来源:OpenAI
- 摘要:实时视觉对话 API,摄像头 + 屏幕共享 + 语音,延迟 < 400ms。
⚙️ 后端 / 架构
2. Docker 多阶段构建最佳实践
- 链接:https://docs.docker.com/build/building/multi-stage
- 来源:Docker 官方
- 摘要:Docker BuildKit 多阶段构建,从 1GB 镜像到 100MB。
3. eBPF + Docker 集成
- 链接:https://www.docker.com/blog/ebpf-integration
- 来源:Docker
- 摘要:Docker 集成 eBPF,零侵入监控容器运行时。
🎨 前端 / Web
4. WebGPU 浏览器全面支持
- 链接:https://web.dev/webgpu-2026
- 来源:web.dev
- 摘要:所有主流浏览器支持 WebGPU,浏览器原生 GPU 计算。
🚀 独立开发 / OPC
5. Paddle 推出订阅分析
- 链接:https://www.paddle.com/analytics
- 来源:Paddle
- 摘要:可视化订阅分析,MRR / Churn / LTV 一站式。
6. Resend 推出 Email Templates Pro
- 链接:https://resend.com/templates-pro
- 来源:Resend
- 摘要:200+ 邮件模板,React Email 兼容,开箱即用。
数据来源:HN / Reddit / 各厂博客 采集时间:2026-06-28 09:00 (UTC+8)
📝
今日深度文
Docker 多阶段构建最佳实践:从 1GB 到 100MB
一句话结论:多阶段构建 + 精简基础镜像 = 生产级 Docker 镜像。Node.js / Go / Rust 都有不同优化策略。
背景
Docker 镜像大小直接影响:
- 拉取速度(CI/CD 慢)
- 部署速度(K8s 启动慢)
- 存储成本(镜像仓库费用)
- 安全风险(大镜像 = 更多攻击面)
目标:生产镜像 < 200MB。
反面案例
# ❌ 单阶段构建
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
# 镜像大小:1.2GB
# 包含:node + npm + devDependencies + 源码
正面案例:Node.js 多阶段
# ✅ 阶段 1:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ✅ 阶段 2:生产
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# 只复制必要文件
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
# 非 root 用户
USER node
CMD ["node", "dist/main.js"]
# 镜像大小:180MB(-85%)
6 个真实案例
案例 1:Node.js + Next.js
# 阶段 1:依赖
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
# 阶段 2:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# 阶段 3:生产
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]
案例 2:Go(极小镜像)
# 阶段 1:构建
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server
# 阶段 2:scratch(零基础镜像!)
FROM scratch
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
# 镜像大小:15MB(Go 的优势)
案例 3:Rust
# 阶段 1:构建
FROM rust:1.75-alpine AS builder
WORKDIR /app
RUN apk add --no-cache musl-dev
COPY . .
RUN cargo build --release
# 阶段 2:极简运行
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
WORKDIR /app
COPY --from=builder /app/target/release/myapp /usr/local/bin/
EXPOSE 8080
CMD ["myapp"]
# 镜像大小:30MB
案例 4:Python + FastAPI
# 阶段 1:构建
FROM python:3.12-slim AS builder
WORKDIR /app
RUN pip install --no-cache-dir poetry
COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt
RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
# 阶段 2:生产
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /wheels /wheels
RUN pip install --no-cache-dir --no-index --find-links=/wheels /wheels/*
COPY . .
# 非 root
RUN useradd -m appuser
USER appuser
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]
# 镜像大小:250MB
案例 5:Java + Spring Boot
# 阶段 1:构建
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./gradlew bootJar
# 阶段 2:JRE 运行时(无 JDK)
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
# 镜像大小:280MB
案例 6:Next.js + Bun(实验性)
# 阶段 1:用 Bun 构建
FROM oven/bun:1 AS builder
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
# 阶段 2:极简运行时
FROM oven/bun:1-slim
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["bun", "server.js"]
# 镜像大小:120MB
7 个优化技巧
1. 选择精简基础镜像
distroless: ~2MB(推荐生产用)
alpine: ~5MB
slim: ~80MB(Debian 精简)
ubuntu: ~70MB
node: ~900MB(默认含大量工具)
2. 利用层缓存
# ❌ 反面:每次构建都失效所有缓存
COPY . .
RUN npm install
# ✅ 正面:先复制依赖文件(package.json)
COPY package*.json ./
RUN npm install
COPY . .
# 依赖层在源码不变时可复用
3. .dockerignore
# .dockerignore
node_modules
.git
.next
dist
coverage
.env*
*.log
README.md
4. 多阶段合并 RUN
# ❌ 每条 RUN 一个层
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
# ✅ 合并 + 清理
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
git && \
rm -rf /var/lib/apt/lists/*
5. 使用 BuildKit 缓存挂载
# syntax=docker/dockerfile:1.6
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
COPY . .
RUN --mount=type=cache,target=/app/.next/cache \
npm run build
6. 分析镜像
# 使用 dive 分析
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive:latest my-image:tag
# 或 docker history
docker history my-image:tag
7. 安全扫描
# Trivy 扫描漏洞
trivy image my-image:tag
# 或 Docker Scout
docker scout cves my-image:tag
完整 .dockerignore 示例
# Git
.git
.gitignore
# Dependencies
node_modules
**/node_modules
bower_components
# Build artifacts
.next
dist
build
out
coverage
# Environment
.env
.env.*
!.env.example
# Logs
*.log
npm-debug.log*
yarn-debug.log*
# IDE
.vscode
.idea
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Docs
README.md
CHANGELOG.md
docs/
# Test
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/__tests__/
实战:部署到生产
GitHub Actions 构建
# .github/workflows/docker.yml
name: Docker Build
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
部署到 K8s
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: ghcr.io/me/my-app:latest
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /health
port: 3000
5 个常见坑
坑 1:基础镜像不匹配
# ❌ 在 ARM Mac 上构建 x86 镜像
# 运行时会崩溃
# ✅ 用 buildx 多平台
docker buildx build --platform linux/amd64,linux/arm64 .
坑 2:COPY 整个目录
# ❌ 复制所有文件(包括 .git / node_modules)
COPY . /app
# ✅ 用 .dockerignore 排除
坑 3:忘记清理缓存
# ❌ apt 缓存占空间
RUN apt-get update && apt-get install -y curl
# ✅ 清理
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
坑 4:时区问题
# ❌ 容器时间是 UTC
# ✅ 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
坑 5:使用 latest 标签
# ❌ image: node:latest
# 不可复现
# ✅ 固定版本
image: node:20.11-alpine
我的看法
Docker 镜像优化的核心原则:
- 小基础镜像:alpine / distroless / scratch
- 多阶段构建:构建产物 ≠ 运行时
- 层缓存友好:依赖与代码分离
- 定期扫描:漏洞 / 过期依赖
- 持续监控:镜像大小 + 启动时间
目标:
| 类型 | 大小目标 |
|---|---|
| Go | < 30MB |
| Rust | < 50MB |
| Node.js | < 200MB |
| Python | < 300MB |
| Java | < 400MB |
参考
本文示例基于 2026 年 6 月最新 Docker 24.x,所有镜像大小实测。
📚 同主题文章
⚙️后端 / 架构·
GitHub Actions + DevOps 实战:从 CI 到自动化部署
GitHub Actions 是 2026 年独立开发者的标配 DevOps 工具。本文从 0 到生产级 CI/CD,含 8 个实战 Workflow + 测试 + 部署 + 安全扫描 + 性能监控。
GitHub ActionsDevOpsCI/CD
⚙️后端 / 架构·
Deno 2 + Hono 实战:现代边缘运行时全栈开发
Deno 2 + Hono 是 2026 年最强的边缘运行时组合:原生 TypeScript、内置工具链、冷启动 < 5ms。本文从入门到生产,含 4 个实战项目 + 性能对比 + 迁移指南。
DenoHono边缘运行时
⚙️后端 / 架构·
Docker 实战:从入门到生产级多阶段镜像
Docker 是 2026 年部署的事实标准。本文从 0 到生产级多阶段构建,含 4 个真实项目 + 镜像优化 10x + Docker Compose 编排实战。
DockerDevOps容器化