萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux Docker 鏡像瘦身實戰:從 500MB 壓縮到 10MB 以下

Docker 鏡像體積直接影響部署速度、儲存成本與安全攻擊面。本文透過「基礎鏡像替換、多階段建構、層數優化、快取清理」四大策略,示範如何將一個 Ubuntu+Nginx+2048 遊戲的示範專案從傳統寫法的 ~500MB 壓縮至 10MB 以下。

一、傳統寫法的痛點分析

傳統 Dockerfile 架構

# 傳統 Dockerfile(~500MB+)
FROM ubuntu:12.04
RUN apt-get update
RUN apt-get install -y nginx zip curl
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
RUN curl -o /usr/share/nginx/www/master.zip -L https://codeload.github.com/gabrielecirulli/2048/zip/master
RUN cd /usr/share/nginx/www/ && unzip master.zip && mv 2048-master/* . && rm -rf 2048-master master.zip
EXPOSE 80
CMD ["/usr/sbin/nginx", "-c", "/etc/nginx/nginx.conf"]

四大問題

  1. 基礎鏡像過大:ubuntu:12.04 基礎層即 100MB+
  2. 層數過多:每個 RUN 產生一層,中間產物(apt cache、下載的 zip、解壓暫存檔)永久保留
  3. 無清理機制:安裝套件後未清理 /var/lib/apt/lists/*
  4. 單階段建構:建構工具(curl、unzip、gcc 等)隨鏡像發布

二、極致瘦身版 Dockerfile(Alpine + 多階段)

# 階段 1:建構階段(含建構工具)
FROM alpine:latest AS builder
RUN apk add --no-cache nginx unzip curl
RUN mkdir -p /usr/share/nginx/html && \
    curl -sSL https://codeload.github.com/gabrielecirulli/2048/zip/master -o /tmp/2048.zip && \
    unzip -q /tmp/2048.zip -d /tmp && \
    mv /tmp/2048-master/* /usr/share/nginx/html/ && \
    rm -rf /tmp/2048.zip /tmp/2048-master

# 階段 2:運行階段(極精簡)
FROM alpine:latest
COPY --from=builder /usr/share/nginx/html /usr/share/nginx/html
COPY --from=builder /etc/nginx/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

三、四大瘦身策略深度解析

1. 基礎鏡像替換:Alpine Linux

  • 基於 musl libc + busybox,基礎鏡像 ~5MB(vs Ubuntu 100MB+)
  • 套件管理器 apk 極快,--no-cache 避免快取殘留
  • 注意:musl vs glibc 相容性(多數 Go/靜態編譯/解釋語言無影響)

2. 多階段建構

# 語法:FROM  AS   →  COPY --from=  
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp .

FROM alpine:3.18
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/myapp /usr/local/bin/myapp
CMD ["myapp"]
  • 最終鏡像僅包含運行時檔案,建構工具、原始碼、測試檔全部捨棄
  • 支援多個 FROM,每階段獨立快取

3. 層數合併與快取清理

4. .dockerignore 排除無關檔案

# .dockerignore
.git
.gitignore
README.md
*.log
node_modules
vendor
*.tar.gz
Dockerfile*
docker-compose*

四、進階瘦身技巧

1. Distroless / Scratch 基礎鏡像

# Google Distroless(含 ca-certificates、tzdata、glibc)
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/myapp /myapp
USER nonroot:nonroot
ENTRYPOINT ["/myapp"]

# Scratch(完全空白,僅適合完全靜態連結二進位)
FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]

2. 壓縮層

# 建構時啟用壓縮(需 Docker 20.10+)
DOCKER_BUILDKIT=1 docker build --compress -t myapp:latest .

3. 分析鏡像體積工具

  • docker history --no-trunc myimage:查看各層大小
  • docker run --rm -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest myimage:互動式層級分析
  • docker-slim:自動分析並生成精簡鏡像

五、實測對比結果

反模式最佳實踐
多個獨立 RUN單一 RUN 串聯 &&,末尾清理快取
RUN apt-get update && apt-get install -y pkgRUN apt-get update && apt-get install -y pkg && rm -rf /var/lib/apt/lists/*
COPY 後再 RUN 修改權限COPY --chown=user:group 或建構階段預設權限
版本基礎鏡像鏡像大小建構時間關鍵優化
傳統ubuntu:12.04~520 MB~3 min無
Alpine 單階段alpine:latest~45 MB~1 min基礎鏡像替換
Alpine 多階段alpine:latest~12 MB~1.5 min建構/運行分離
Distroless 多階段gcr.io/distroless/static~8 MB~1.5 min無 Shell、最小攻擊面
Scratch 靜態編譯scratch~3 MB~2 min僅二進位檔

遵循「最小基礎鏡像 + 多階段建構 + 單層合併 + 徹底清理」原則,配合 dive 定期審視層級結構,可將生產鏡像控制在極小體積,加速 CI/CD 流水線與生產部署。

copyright © 萬盛學電腦網 all rights reserved