Docker v18.09上引入的一组增强功能,它的名字叫做BuildKit,它可以减少构建时间,缩小镜像尺寸等特性,下面我们重点介绍一下测试一下它是如何加快镜像构建的。
- 首先需要docker升级到较新的版本,具体可以参考
1.1查看本地是否有docker,以及docker版本
1.2 删除旧版本的docker
yum remove docker docker-common docker-client docker-compose
1.3 安装最新版docker
curl -fsSL https://get.docker.com/ | sh
1.4 验证docker版本
我们首先在服务器上分别上传编写好的Dockerfile和helloworld-0.0.1-SNAPSHOT.jar上传带有docker最新版本的linux服务器
我们查看一下Dockerfile内容
# Use the Official OpenJDK image for a lean production stage of our multi-stage build.
# https://hub.docker.com/_/openjdk
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM docker.io/anapsix/alpine-java
# Copy the jar to the production image from the builder stage.
COPY /helloworld-*.jar /helloworld.jar
# Run the web service on container startup.
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"]
以上的dockerfille 很好理解 加载alpine-java带有java运行环境的基础镜像,复制helloworld.jar到容器内,设置运行环境。
下面我们重点介绍一下测试
2.1 使用普通的 docker bulid 编译镜像,命令行如下
time docker build --no-cache -t=yf.registry.965432.com/sjjcb/helloworld-java-spring:helloworld001 .
我们知道如果docker build之前如果有依赖的基础镜像会从缓存中直接获取,这样对比就看不出来BuildKit优势,我们这里面统一设置--no-cache,执行结果如下:
可以看到打包执行时间 3.036秒,这个东西前面我们docker.io/anapsix/alpine-java 镜像是已经有的,所以执行3秒,这个我们是可以接受的。
2.2 使用BuildKit docker bulid 编译镜像,命令行如下:
time DOCKER_BUILDKIT=1 docker build --no-cache -t=yf.registry.965432.com/sjjcb/helloworld-java-spring:helloworld001 .
在执行以上命名前,我们启用 BuildKit 必须先设置 环境变量(由于是同一台机器,我只能临时设置这个值)
export DOCKER_BUILDKIT=1
下面执行 DOCKER_BUILDKIT=1 docker build 情况:
从以上执行我们可以看到 执行时间在1.749秒,比上面提升了50%,就是使用了DOCKER_BUILDKIT=1 这个属性,其他都没有变化。
3.启用 BuildKit 之后,RUN 新增了新的指令,这些指令也可以加快我们编译打包速度。下面我们挑选几个指令介绍
- RUN --mount=type=cache
RUN --mount=type=bind
RUN --mount=type=tmpfs
RUN --mount=type=secret
RUN --mount=type=ssh
目前,几乎所有的程序都会使用依赖管理工具,例如 Go 中的 go mod、Node.js 中的 npm 等等,当我们构建一个镜像时,往往会重复地从互联网中获取依赖包,难以缓存,大大降低了镜像的构建效率。
我们以前后端分离项目前端项目打包为例重点介绍一下RUN --mount=type=cache,dockerfile文件如下
FROM node:alpine as builder
WORKDIR /app
COPY package.json /app/
RUN npm i --registry=https://registry.npm.taobao.org \
&& rm -rf ~/.npm
COPY src /app/src
#RUN npm run build
#FROM nginx:alpine
#COPY --from=builder /app/dist /app/dist
3.1 我们通过普通 docker bulid 编译镜像,命令行如下
time docker build --no-cache -t=yf.registry.965432.com/sjjcb/node:node001 .
我们修改dockerfile 增加RUN --mount=type=cache 对比
FROM node:alpine as builder
WORKDIR /app
COPY package.json /app/
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npm.taobao.org
COPY src /app/src
#RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
# --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
# npm run build
#FROM nginx:alpine
# COPY --from=builder /app/dist /app/dist
# 为了更直观的说明 from 和 source 指令,这里使用 RUN 指令
#RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
# --mount=type=cache,target/tmp/dist,from=my_app_dist,sharing=locked \
# mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
第一个 RUN 指令执行后,id 为 my_app_npm_module 的缓存文件夹挂载到了 /app/node_modules 文件夹中。多次执行也不会产生多个中间层镜像。
执行后0.788秒
呵呵是不是比较快啊,详细资料可以参考
https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md