多阶段构建 - 镜像体积优化 99%

知识库
知识库文档
/tech-stacks/docker/examples/多阶段构建 - 镜像体积优化 99%.md

文档

目标

演示 Docker 多阶段构建(Multi-stage Build)技术,将一个 Go 应用从源码编译到最终运行镜像,压缩镜像体积从 ~800MB 降至 ~10MB。

完整代码

示例应用(main.go)

package main

import (
    "fmt"
    "net/http"
    "os"
)

func handler(w http.ResponseWriter, r *http.Request) {
    hostname, _ := os.Hostname()
    fmt.Fprintf(w, "Hello from %s (Go %s)\n", hostname, r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    fmt.Println("Server listening on :8080")
    http.ListenAndServe(":8080", nil)
}

Dockerfile(多阶段构建)

# ============ 阶段1:编译 ============
FROM golang:1.22-alpine AS builder

# 设置国内代理(可选)
ENV GOPROXY=https://goproxy.cn,direct

WORKDIR /src
COPY main.go .

# 静态编译,剥离调试信息,减小体积
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app main.go

# ============ 阶段2:运行 ============
FROM scratch

# 从构建阶段复制编译好的二进制
COPY --from=builder /app /app

# scratch 镜像没有时区文件,需要的话可以复制
# COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo

EXPOSE 8080
ENTRYPOINT ["/app"]

对比:单阶段构建(不推荐)

# 不推荐 — 镜像体积 ~800MB
FROM golang:1.22
WORKDIR /src
COPY main.go .
RUN go build -o /app main.go
EXPOSE 8080
ENTRYPOINT ["/app"]

Docker Compose 生产级编排

# docker-compose.yml
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: my-go-app:latest
    ports:
      - "8080:8080"
    environment:
      - APP_ENV=production
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 128M
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

运行步骤

# 1. 构建镜像
docker build -t my-go-app:multi -f Dockerfile .

# 2. 查看镜像大小
docker images | grep my-go-app
# my-go-app   multi    8.5MB    ← 多阶段构建
# my-go-app   single   823MB    ← 单阶段构建

# 3. 运行容器
docker run -d --name go-app -p 8080:8080 my-go-app:multi

# 4. 测试
curl http://localhost:8080/hello
# Hello from abc123def (Go hello)

# 5. 查看层信息
docker history my-go-app:multi

# 6. 使用 dive 分析镜像(需安装)
dive my-go-app:multi

预期输出

镜像大小对比:
  单阶段镜像:823 MB
  多阶段镜像:8.5 MB  ← 减少 ~99%

docker history 输出:
  IMAGE          CREATED         SIZE
  <missing>      1 min ago       8.5MB  ← 最终只有二进制

关键点

  • FROM scratch 是空镜像,不含任何 OS 层,安全性极高
  • CGO_ENABLED=0 强制纯 Go 静态链接,不依赖 libc
  • -ldflags="-s -w" 去除符号表和调试信息
  • COPY --from=builder 跨阶段复制,构建依赖不进入最终镜像
  • 多阶段适合所有编译型语言:Go、Rust、C/C++、Java(jlink)

信息

路径
/tech-stacks/docker/examples/多阶段构建 - 镜像体积优化 99%.md
更新时间
2026/5/31