Docker 的多阶段构建
作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/15223414.html
目录
需求
第一步:原始方式构建镜像
第二步:取二进制文件构建镜像
第三步:多阶段构建
需求
我们 Build 一个应用的时候,将我们的源代码也构建进去的,这对于类似于 golang 这样的编译型语言肯定是不行的,因为实际运行的时候我只需要把最终构建的二进制包给你就行,把源码也一起打包在镜像中,需要承担很多风险,即使是脚本语言,在构建的时候也可能需要使用到一些上线的工具,这样无疑也增大了我们的镜像体积。所以对于golang语言运行于docker之上的时候,只出现二进制文件即可。
比如有如下程序需要在docker中运行:
1 2 3 4 5 6 7 8 9 10 11 12 | package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { router := gin.Default() router.GET( "/ping" , func(c *gin.Context) { c.String(http.StatusOK, "PONG" ) }) router.Run( ":8080" ) } |
第一步:原始方式构建镜像
编写dockerfile文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | FROM golang:1.14-alpine ENV CGO_ENABLED=0 ENV GOPROXY= "http://10.11.100.127/repository/goproxy/" RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \ && apk add --update --no-cache ca-certificates curl make git gcc libtool musl-dev RUN mkdir /app \ && mkdir -p /app/ static COPY . /app WORKDIR /app RUN go mod vendor && go build -o main CMD [ "/app/main" ] |
构建镜像:
1 | docker build -t demo-test:old . |
查看镜像:
可以看到,镜像文件有570多M。
第二步:取二进制文件构建镜像
其实我们只需要他的二进制文件,所以需要拿去二进制文件即可:
1 2 3 | docker create --name myapp demo-test:old docker cp myapp:/app/app-server ./app-server docker rm -f extract |
获取二进制文件后,继续编写第二个dockerfile文件: cat Dockerfile.old
1 2 3 4 5 6 | FROM alpine:latest RUN apk add -U tzdata RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime WORKDIR /root/ COPY app-server . CMD [ "./app-server" ] |
查看镜像:
此时可以看到镜像文件只有24.1MB了!
第三步:多阶段构建
Docker 17.05版本以后,官方就提供了一个新的特性:Multi-stage builds
(多阶段构建)。 使用多阶段构建,你可以在一个 Dockerfile
中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并表示开始一个新的构建阶段。你可以很方便的将一个阶段的文件复制到另外一个阶段,在最终的镜像中保留下你需要的内容即可。
我们可以调整前面一节的 Dockerfile
来使用多阶段构建:(保存为Dockerfile)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | FROM golang:1.14-alpine as build-env ENV CGO_ENABLED=0 ENV GOPROXY= "http://10.11.100.127/repository/goproxy/" RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \ && apk add --update --no-cache ca-certificates curl make git gcc libtool musl-dev RUN mkdir /app \ && mkdir -p /app/ static COPY . /app WORKDIR /app RUN go mod vendor && go build -o /app/main FROM alpine:latest RUN apk add -U tzdata RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY -- from =build-env /app/main /usr/local/bin/app-server EXPOSE 8080 CMD [ "app-server" ] |
注意:COPY中的--from=build-env可以直接使用第一阶段生成的文件,相当于接管了第一阶段的上下文。
构建镜像:
1 | docker build -t multi-state-demo: new . |
查看镜像:
可以看到,多阶段构建和之前分为两步构建,效果一样!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」