Docker多阶段构建实战:镜像瘦身术
·
在现代软件开发中,容器化技术已经成为一个不可或缺的部分。Docker 作为最流行的容器化平台之一,为我们提供了强大的工具来打包、发布和运行应用程序。然而,随着应用程序的增长,Docker 镜像的大小也往往会变得庞大,这不仅增加了构建时间,也可能影响到容器的启动速度。今天,我们将探讨如何通过 Dockerfile 的多阶段构建功能来解决这个问题。
实战案例:多阶段构建
什么是多阶段构建?
多阶段构建允许我们在 Dockerfile 中定义多个构建阶段,每个阶段都可以使用不同的基础镜像,并且可以有选择地将文件从一个阶段复制到另一个阶段。这种方法让我们能够分离出编译/构建环境与最终运行环境,从而大幅减少生成的 Docker 镜像的体积。
利用多阶段构建,可以大大减小镜像的大小,但要注意相关依赖文件都要复制到新构建中才能正常运行容器。多阶段构建比较适用于静态编译的程序,比如:Golang。
另外在Dockerfile文件中删除文件,也不会让镜像变小,也可以利用多阶段构建缩小镜像。
多阶段构建
[root@ubuntu2404 golang]#vim hello.go
package main
import "fmt"
func main() {
fmt.Println("hello, world")
}
#第一次构建
[root@ubuntu2404 golang]#cat build.sh
#!/bin/bash
docker build -t go-hello:$1 .
[root@ubuntu2404 golang]#cat Dockerfile
FROM golang:alpine3.22
COPY hello.go /opt
WORKDIR /opt
RUN go build hello.go
CMD "./hello"
[root@ubuntu2404 golang]#bash build.sh v1.0
[root@ubuntu2404 golang]#docker run --name hello go-hello:v1.0
hello, world
#第二次优化
[root@ubuntu2404 golang]#cp Dockerfile Dockerfile-v1.0
[root@ubuntu2404 golang]#vim Dockerfile
FROM golang:alpine3.22 as builder
WORKDIR /opt
COPY hello.go .
RUN go build hello.go
FROM alpine:latest
WORKDIR /opt
COPY --from=builder /opt/hello /opt/hello
CMD ["./hello"]
[root@ubuntu2404 golang]#bash build.sh v2.0
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
Install the buildx component to build images with BuildKit:
https://docs.docker.com/go/buildx/
Sending build context to Docker daemon 5.12kB
Step 1/7 : FROM golang:alpine3.22 as builder
---> 88aa171b8c32
Step 2/7 : COPY hello.go /opt
---> Using cache
---> 4061c57f99a9
Step 3/7 : WORKDIR /opt
---> Using cache
---> 0c70cd292561
Step 4/7 : RUN go build hello.go
---> Using cache
---> 896bfd2a09b5
Step 5/7 : FROM alpine:3.3
---> a6fc1dbfa81a
Step 6/7 : COPY --from=builder /opt/hello /opt/hello
---> cd347a44c5bb
Step 7/7 : CMD ["/hello"]
---> Running in 1df61f494aee
---> Removed intermediate container 1df61f494aee
---> 44574120c5d0
Successfully built 44574120c5d0
Successfully tagged go-hello:v2.0
[root@ubuntu2404 golang]#docker run --name hello go-hello:v2.0
hello, world
[root@ubuntu2404 golang]#docker images go-hello
REPOSITORY TAG IMAGE ID CREATED SIZE
go-hello v2.0 44574120c5d0 37 minutes ago 7.03MB
go-hello v1.0 416d9a7cc413 57 minutes ago 296MB
#第三次优化
[root@ubuntu2404 golang]#cat Dockerfile
FROM golang:alpine3.22 as builder
WORKDIR /opt
COPY hello.go .
RUN go build hello.go
FROM scratch
WORKDIR /opt
COPY --from=builder /opt/hello /opt/hello
#COPY --from=0 /opt/hello /hello
CMD ["./hello"]
[root@ubuntu2404 golang]#bash build.sh v3.0
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
Install the buildx component to build images with BuildKit:
https://docs.docker.com/go/buildx/
Sending build context to Docker daemon 5.12kB
Step 1/7 : FROM golang:alpine3.22 as builder
---> 88aa171b8c32
Step 2/7 : WORKDIR /opt
---> Using cache
---> 97b788140589
Step 3/7 : COPY hello.go .
---> Using cache
---> 0789546cb5ee
Step 4/7 : RUN go build hello.go
---> Using cache
---> e6d6aa6e1c54
Step 5/7 : FROM scratch
--->
Step 6/7 : COPY --from=builder /opt/hello /opt/hello
---> f7ef2e1009b0
Step 7/7 : CMD ["/hello"]
---> Running in 81d37bcc8c98
---> Removed intermediate container 81d37bcc8c98
---> 1f3765e7cafb
Successfully built 1f3765e7cafb
Successfully tagged go-hello:v3.0
[root@ubuntu2404 golang]#docker run --name hello1 go-hello:v4.0
hello, world
#比较三次构建的结果
[root@ubuntu2404 golang]#docker images go-hello
REPOSITORY TAG IMAGE ID CREATED SIZE
go-hello v3.0 46aec64556f9 18 seconds ago 2.2MB
go-hello v2.0 44574120c5d0 59 minutes ago 7.03MB
go-hello v1.0 416d9a7cc413 About an hour ago 296MB
结论
通过采用 Dockerfile 的多阶段构建方法,我们可以有效地减小 Docker 镜像的尺寸,加快构建和部署的速度。此外,它还帮助我们保持了良好的开发和生产环境之间的分离,使得维护更加容易。
希望这篇指南能为您提供一些关于如何利用 Docker 多阶段构建来优化您的项目部署的见解。尝试一下吧,看看它是如何改变你的工作流程的!
更多推荐
所有评论(0)