docker构建还能这么玩

9 篇文章 0 订阅
6 篇文章 0 订阅
前言

多阶段构建(Multi-stage builds)是从 Docker 17.05 版本开始引入的功能。这个功能允许在单个 Dockerfile 中定义多个构建阶段,并且在最终镜像中只包含所需的内容,从而减小镜像的大小。通过多阶段构建,可以将构建环境和运行环境分开,使得最终的镜像更加轻量化,减少了不必要的依赖和文件

使用多阶段构建
# syntax=docker/dockerfile:1
FROM golang:1.21 
WORKDIR /src
COPY <<EOF ./main.go
package main

import "fmt"

func main() {
  fmt.Println("hello, world")
}
EOF
RUN go build -o /bin/hello ./main.go

FROM scratch
COPY --from=0 /bin/hello /bin/hello
CMD ["/bin/hello"]

如上例子,可以有两个或多个 FROM 关键字,第一个 FROM 阶段作的事相当于把程序编译成一个二进制文件,第二个 FROM 阶段从第一阶段拷贝编译后的产物,这样最终生成镜像的体积,因为丢弃了编译阶段的依赖了,就小了很多

命名构建阶段

上面的例子,因为没有设置别名,默认情况 docker 内部会给每一个 FROM 按顺序从 0 开始自增设置编号,所以我们用了 COPY --from=0 /bin/hello /bin/hello这样的方式来引用,这样缺点在于,如果构建阶段的顺序发生了变化,那么我们引用的编号也要修改,这样就不够优雅了,好在支持设置别名功能,将上面的例子改造后如下:

# syntax=docker/dockerfile:1
FROM golang:1.21 as build
WORKDIR /src
COPY <<EOF /src/main.go
package main

import "fmt"

func main() {
  fmt.Println("hello, world")
}
EOF
RUN go build -o /bin/hello ./main.go

FROM scratch
COPY --from=build /bin/hello /bin/hello
CMD ["/bin/hello"]
构建部分阶段

多阶段构建,支持构建部分 FROM 的内容,这样可以方便调试,比如我想看下编译后的内容,就没必要每次还得执行编译后的其他阶段,使用方法如下:

docker build --target build -t hello .
从外部镜像作拷贝数据

前面我们都是从上一个 FROM 阶段拷贝的数据,假如我已经有现成的镜像了,在使用 FROM 拷贝就略显得臃肿了,好在 COPY --from 指令支持从单独的镜像(本地或远程)里面拷贝数据,使用如下:

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

这个功能非常有用,假如我们应用镜像运行时依赖多个中间件才能正常工作,那么传统的做法需要做一个大而全的基础镜像,通过这种方式我们就可以组合出更灵活按需适配的场景,从而大幅度减小优化镜像的体积

使用上一阶段作为新阶段

这个很简单,就是可以使用上一阶段构建完的结构,作为新的阶段的起步依赖,例子如下:

# syntax=docker/dockerfile:1

FROM alpine:latest AS builder
RUN apk --no-cache add build-base

FROM builder AS build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp

FROM builder AS build2
COPY source2.cpp source.cpp
RUN g++ -o /binary source.cpp

BuildKit和普通的builder的区别

BuildKit 于 Docker 18.09 版本开始引入。BuildKit 旨在提供更快速、更灵活、更安全的构建体验,以及更好的多阶段构建支持。

BuildKit 仅仅构建其依赖的前置,而 builder 则会构建所有依赖,如下例子:

# syntax=docker/dockerfile:1
FROM ubuntu AS base
RUN echo "base"

FROM base AS stage1
RUN echo "stage1"

FROM base AS stage2
RUN echo "stage2"

激活 BuildKit 后,仅仅需要构建 base和 stage2 即可

DOCKER_BUILDKIT=1 docker build --no-cache -f Dockerfile --target stage2 .

没激活 BuildKit 后,则需要构建 base,stage1 和 stage2

DOCKER_BUILDKIT=0 docker build --no-cache -f Dockerfile --target stage2 .
总结

使用多阶段构建可以帮助优化和简化容器镜像的构建过程,减小镜像大小,简化构建流程,提升构建灵活性,加速构建速度,优化镜像层次结构,减少依赖关系,从而提高了容器化应用程序的部署效率和性能

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值