「Docker 镜像多阶段构建」:让你的容器更小、更快、更安全! ...

打印 上一主题 下一主题

主题 1969|帖子 1969|积分 5907

欢迎关注我的公众号「DevOps和k8s全栈技术」,进公众号【服务】栏,可以看到技术群,点击即可参加学习交流群。↓↓↓

  关注公众号,免费学技术,免被割哦~
  在容器化应用的开发过程中,镜像体积越小,构建速率越快,摆设服从也就越高。而 Docker 多阶段构建(Multi-Stage Build)是一种优化 Docker 镜像的利器,可以显著减少终极镜像的体积,同时保持构建过程的机动性。本文将详细先容多阶段构建的根本原理、优化本领,并结合实战案例,帮助你打造更轻量、高效的 Docker 镜像。
  1. 传统构建 vs. 多阶段构建

  在没有使用多阶段构建之前,我们通常会在一个 Dockerfile 中完成全部的构建步骤,包罗编译、打包、安装依赖等。这种方式的主要问题是:
  1)冗余依赖:构建时的工具和库会被打包进终极镜像,导致体积巨大。
  2)安全性低:多余的工具和开发环境增长了安全风险。
  3)构建服从低:每次构建都会重新拉取和安装全部依赖。
  多阶段构建的核心头脑是:将构建过程拆分成多个阶段,只在终极阶段保留须要的文件,避免无关的构建工具、编译器等被打包进终极镜像,从而优化镜像体积,提高安全性和构建服从。
  
  2. 多阶段构建的根本用法

  示例:构建 Go 应用

  假设我们有一个简朴的 Go Web 应用(main.go):
  1. package main
  2. import (    "fmt"    "net/http")
  3. func handler(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "Hello, Docker Multi-Stage Build!")}
  4. func main() {    http.HandleFunc("/", handler)    http.ListenAndServe(":8080", nil)}
复制代码
如果直接编写 Dockerfile,可能会这样做:
  1. FROM golang:1.21 AS builderWORKDIR /appCOPY . .RUN go build -o app
  2. FROM alpine:latestWORKDIR /root/COPY --from=builder /app/app .CMD ["./app"]
复制代码
解析:

  

  • 第一阶段(builder):
  

  • 使用 golang:1.21 作为基础镜像,包含 Go 语言环境。
  • 复制源代码并编译,天生二进制文件 app。
  

  • 第二阶段(alpine):


    • 仅使用 alpine:latest 作为运行环境,体积仅 5MB。
    • 从 builder 阶段拷贝编译好的二进制文件 app,避免携带 Go 开发环境。
    • 运行时只保留最小化的环境,提高安全性和服从。
      优化结果:如果使用 golang:1.21 直接构建,终极镜像巨细可能凌驾 900MB;但采用多阶段构建后,终极镜像只有 10MB 左右!
      3. 深入优化 Docker 多阶段构建

      多阶段构建固然能优化镜像巨细,但仍有进一步优化的空间。
      1️⃣ 减少层数,优化缓存

      Docker 镜像的构建是分层的,每一条 RUN、COPY、ADD 指令都会创建新的层。为了提高构建服从,可以:
      1)合并 RUN 指令,减少层数,比方:
    1. RUN apt-get update && apt-get install -y \    curl \    git \    && rm -rf /var/lib/apt/lists/*
    复制代码
    2)公道利用缓存:只管避免频繁变动 COPY 指令,以减少不须要的缓存失效。比方:
    1. COPY go.mod go.sum .  RUN go mod download  COPY . .  RUN go build -o app
    复制代码


    • 优化点:先复制 go.mod 和 go.sum 并执行 go mod download,可以利用 Docker 层缓存,加速构建。
      2️⃣ 使用更小的基础镜像

      基础镜像的选择直接影响终极镜像巨细。建议:
      

    • 使用 Alpine:比方 
      alpine:latest 体积仅 5MB,比 ubuntu(约 29MB)更小。
      

    • 使用 Distroless:Google 提供的 
      distroless 镜像进一步精简,仅包含运行时环境。
      优化后的 Dockerfile 示例:
    1. FROM golang:1.21 AS builderWORKDIR /appCOPY . .RUN go build -o app
    2. FROM gcr.io/distroless/staticCOPY --from=builder /app/app /CMD ["/app"]
    复制代码
    终极镜像 甚至小于 5MB,比 Alpine 方案更精简!
      3️⃣ 避免 root 运行,提高安全性

      默认情况下,容器中的历程以 root 运行,存在安全风险。可以在 Dockerfile 中添加一个非 root 用户:
    1. RUN addgroup -S appgroup && adduser -S appuser -G appgroupUSER appuser
    复制代码
    这样,容器中的应用将以 appuser 运行,避免潜伏的权限提拔漏洞。
      4️⃣ 构建参数化,提拔可维护性

      可以通过 ARG 通报变量,使 Dockerfile 更加通用,比方:
    1. ARG GO_VERSION=1.21FROM golang:${GO_VERSION} AS builder
    复制代码
    这样,可以在构建时指定 Go 版本:
    1. docker build --build-arg GO_VERSION=1.20 -t myapp .
    复制代码
    让 Dockerfile 更加机动,可复用性更高。
      4. 总结

      ✅ 多阶段构建的核心优势

      

    • 减小镜像体积:去除构建依赖,仅保留运行时环境。
    • 提拔构建服从:公道利用缓存,提高 CI/CD 速率。
    • 增强安全性:减少无用软件,避免 root 运行,提高安全性。
    • 提高可维护性:使用 ARG变量,让构建更机动。
      通过 Docker 多阶段构建,我们可以在保持开发体验的同时,构建更加轻量、高效、安全的容器镜像。如果你还在为 Docker 镜像太大、构建慢、漏洞多而头疼,不妨试试多阶段构建,让你的容器更快、更安全、更高效!
    继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表