如何优化CI中不断优化docker build速度

当我们在完全使用gitlab runner,或者其他工具,借助完整的Dockerfile完成项目镜像制作中时,大大提高了我们的运维发布效率,但是越来越长的docker build时间也成为快速发布上线的障碍了,我们就来总结一下有哪些优化docker build的方法。

1. 充分利用docker build镜像分层缓存策略

  • 这也是我们最常用的第一种加速构建镜像的方式,以nodejs项目为例:
FROM node:12.18-alpine
LABEL maintainer="xxx"

# 安装常用工具链
RUN \
  sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
  apk add --no-cache \
    bash \
    vim \
    make \
    tzdata \
    git python make gcc g++ && \
    cp -r -f /usr/share/zoneinfo/Hongkong /etc/localtime

ENV NODE_ENV=production

WORKDIR /data/
# 先拷贝文件变化需要安装依赖的文件,例如nodejs的package.json,java项目的pom.xml等
COPY package.json ./
COPY yarn.lock ./
COPY .yarnrc ./

RUN yarn --no-cache

# 在完成依赖安装后,我们在copy代码进来,如此一来
# 当依赖未变化时,就不需要重复运行以来安装过程了。
COPY ./ ./

EXPOSE 8080
ENTRYPOINT [ "/entrypoint.sh" ]
CMD ["yarn", "start"]

2. 使用多阶段构建镜像

  • 以react前端项目为例
FROM node:12.16-alpine as builder
LABEL maintainer="xxx"

RUN \
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add git python make gcc g++
ENV NODE_ENV development

WORKDIR /data/

COPY package.json ./
COPY .yarnrc ./
COPY yarn.lock ./

RUN yarn install --silent --no-cache

COPY ./ ./
RUN  NODE_ENV=production yarn build

FROM nginx:1.20.1-alpine
LABEL maintainer="xxx"

RUN \
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf
# 关键步骤,我们从上一阶段的 node镜像中,copy出我们需要的最终编译好的前端静态文件
# 放置到nginx镜像中即可,最终景象将只包含nginx以及静态文件
COPY --from=builder /data/dist /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html/

EXPOSE 80

3. 使用docker buildkit在build阶段挂载缓存

  • 这是本文的重点,做了很多的CI项目中后,大家都在思考,如果在docker build阶段,能够挂在上volume来做缓存,那该多好呀,那么,现在,他来了
    在 docker 18.09以上版本,有一个Experimental特性, buildkit工具,默认是没有打开的,我们可以通过 export DOCKER_BUILDKIT=1 之后在进行docker build,或者在 /etc/docker/daemon.json 中配置开启:
{
  "log-driver": "json-file",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "features": { "buildkit": true }
}

开启之后我们就可以修改上面的Dockerfile,来完成一次速度的飞跃:

# syntax=docker/dockerfile:1.3
FROM node:12.16-alpine as builder
LABEL maintainer="xxx"

RUN \
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add git python make gcc g++
ENV NODE_ENV development

WORKDIR /data/

COPY package.json ./
COPY .yarnrc ./
COPY yarn.lock ./

RUN yarn install --silent --no-cache

COPY ./ ./

# 需要开启docker Experimental特性支持,docker version >  18.09 , export DOCKER_BUILDKIT=1
RUN  --mount=type=cache,id=yarn_cache,sharing=shared,target=/usr/local/share/.cache \
     NODE_ENV=production yarn build

FROM nginx:1.20.1-alpine
LABEL maintainer="xxx"

RUN \
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /data/dist /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html/

EXPOSE 80

我们挂在了一个id为yarn_cache的卷到 yarn cache dir下,那么每次安装的依赖本地缓存文件接回写入到缓存中,并在docker build完成之后从运行时中卸载并保存,下载我们就有机会体验拥有本地缓存的完美docker build了。

  • 更多内容我们可以去翻阅官方的docker buildkit相关文档了
    https://docs.docker.com/develop/develop-images/build_enhancements/
    https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md
    目前以上就是简单介绍我目前使用到的所有优化方案了,欢迎小伙伴们来补充。

你可能感兴趣的:(如何优化CI中不断优化docker build速度)