【Docker基础】Dockerfile多阶段构建:Multi-stage Builds详解

目录

[1 什么是Docker多阶段构建](#1 什么是Docker多阶段构建)

[1.1 多阶段构建解决的问题](#1.1 多阶段构建解决的问题)

[1.2 多阶段构建的核心优势](#1.2 多阶段构建的核心优势)

[2 多阶段构建的基本语法](#2 多阶段构建的基本语法)

[3 多阶段构建的典型工作流程](#3 多阶段构建的典型工作流程)

[4 多阶段构建实战示例](#4 多阶段构建实战示例)

[4.1 Golang应用多阶段构建](#4.1 Golang应用多阶段构建)

[4.2 Java应用多阶段构建](#4.2 Java应用多阶段构建)

[4.3 前端应用多阶段构建](#4.3 前端应用多阶段构建)

[5 多阶段构建的高级技巧](#5 多阶段构建的高级技巧)

[5.1 命名构建阶段](#5.1 命名构建阶段)

[5.2 选择性构建阶段](#5.2 选择性构建阶段)

[5.3 使用外部镜像作为阶段](#5.3 使用外部镜像作为阶段)

[5.4 多平台构建](#5.4 多平台构建)

[6 总结](#6 总结)


1 什么是Docker多阶段构建

Docker多阶段构建(Multi-stage Builds)允许在一个Dockerfile中使用多个FROM指令,每个FROM指令都可以使用不同的基础镜像,并且可以选择性地将前一阶段的构建产物复制到后续阶段中。

1.1 多阶段构建解决的问题

在传统的Docker构建过程中,我们经常会遇到以下问题:

  • 构建环境与运行环境混杂:构建工具和依赖会增大最终镜像体积
  • 敏感信息泄露风险:构建过程中可能需要访问私有仓库或使用密钥
  • 构建过程复杂:需要维护多个Dockerfile或复杂的构建脚本
    多阶段构建通过将构建过程分为多个阶段,完美解决了这些问题

1.2 多阶段构建的核心优势

  • 减小镜像体积:只将必要的文件复制到最终镜像
  • 提高安全性:构建依赖和工具不会出现在最终镜像中
  • 简化构建流程:单个Dockerfile管理整个构建过程
  • 提高可维护性:清晰分离构建环境和运行环境

2 多阶段构建的基本语法

  • 多阶段构建的基本语法非常简单,主要依靠多个FROM指令来实现。每个FROM指令开始一个新的构建阶段

    FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

  • --platform:指定构建平台(如linux/amd64)
  • AS :为构建阶段命名(可选但推荐)

3 多阶段构建的典型工作流程

  • 第一阶段:使用包含完整构建工具的基础镜像,编译源代码生成构建产物
  • 第二阶段:使用精简的运行环境基础镜像,仅从第一阶段复制必要的运行文件
  • 最终镜像:只包含运行应用所需的文件,体积小且安全

4 多阶段构建实战示例

4.1 Golang应用多阶段构建

复制代码
# 第一阶段:构建阶段
FROM golang:1.19 AS builder

WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp .

# 第二阶段:运行阶段
FROM alpine:latest  

WORKDIR /root/
COPY --from=builder /app/myapp .
CMD ["./myapp"]
  • 使用golang:1.19作为构建镜像,安装所有构建依赖
  • 编译Go应用,生成可执行文件
  • 使用轻量级alpine作为运行镜像
  • 仅从构建阶段复制编译好的可执行文件

4.2 Java应用多阶段构建

复制代码
# 第一阶段:构建阶段
FROM maven:3.8.6 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src/ /app/src/
RUN mvn package

# 第二阶段:运行阶段
FROM openjdk:17-jdk-slim
COPY --from=build /app/target/myapp.jar /app/myapp.jar
ENTRYPOINT ["java", "-jar", "/app/myapp.jar"]

4.3 前端应用多阶段构建

复制代码
# 第一阶段:构建阶段
FROM node:16 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 第二阶段:运行阶段
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

5 多阶段构建的高级技巧

5.1 命名构建阶段

  • 为构建阶段命名可以提高Dockerfile的可读性:

    FROM golang:1.19 AS builder

    ...

    FROM alpine:latest AS runtime

    ...

    FROM scratch AS release
    COPY --from=runtime / /

5.2 选择性构建阶段

  • 可以只构建特定的阶段:

    docker build --target builder -t myapp:builder .

5.3 使用外部镜像作为阶段

  • 可以从本地或远程镜像复制文件:

    COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

5.4 多平台构建

  • 结合多阶段构建实现多平台支持:

    FROM --platform=BUILDPLATFORM golang:1.19 AS builder ARG TARGETOS TARGETARCH RUN GOOS=TARGETOS GOARCH=$TARGETARCH go build -o /app .

    FROM scratch
    COPY --from=builder /app /app

6 总结

Docker多阶段构建是现代容器化应用开发的重要技术,它通过分离构建环境和运行环境,带来了诸多优势:

  • 显著减小镜像体积:只包含运行所需的文件
  • 增强安全性:减少攻击面,避免敏感信息泄露
  • 简化构建流程:单个Dockerfile管理复杂构建过程
  • 提高可维护性:清晰的阶段划分使构建逻辑更直观
相关推荐
打码人的日常分享12 分钟前
运维服务方案,运维巡检方案,运维安全保障方案文件
大数据·运维·安全·word·安全架构
JCGKS1 小时前
Docker|“ssh: connect to host xxx.xxx.xxx.xxx port 8000: Connection refused“问题解决
docker·ssh·端口·listen·tcp三次握手
荣光波比1 小时前
Nginx 实战系列(一)—— Web 核心概念、HTTP/HTTPS协议 与 Nginx 安装
linux·运维·服务器·nginx·云计算
武文斌771 小时前
单片机:DS18B20测温度、74HC595扩展芯片、8*8LED矩阵
运维·服务器·单片机·嵌入式硬件
惜.己1 小时前
Docker启动失败 Failed to start Docker Application Container Engine.
spring cloud·docker·eureka
fengfuyao9851 小时前
诊断并修复SSH连接Github时遇到的“connection closed“错误
运维·ssh·github
scugxl2 小时前
centos7 docker离线安装
运维·docker·容器
绿箭柠檬茶3 小时前
Ubuntu 使用 Samba 共享文件夹
linux·运维·ubuntu
计算机小手4 小时前
AI 驱动数据分析:开源 SQLBot 项目探索,基于大模型和 RAG 实现精准问数与图表挖掘
经验分享·docker·开源软件
工藤新一¹4 小时前
Linux —— 虚拟进程地址空间
linux·运维·服务器·c/c++·虚拟进程地址空间