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

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

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

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

# 安装常用工具链
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<xx@xxx.com>"

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<xx@xxx.com>"

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<xx@xxx.com>"

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<xx@xxx.com>"

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](#why-docker) [先...
    iOSDevLog阅读 2,137评论 0 3
  • 实例来源:tofar 摘录来源:Docker — 从入门到实践 欢迎大家添加自己的实例 (email: yun_...
    molscar阅读 439评论 1 1
  • 原文地址:https://github.com/KeKe-Li/docker-directive docker 存...
    萌面菠萝阅读 521评论 0 0
  • 本章内容 ◆ Docker简介◆ Docker 镜像与制作◆ Docker 数据管理◆ Docker 网络◆ Do...
    Liang_JC阅读 823评论 0 0
  • 前言 当我们需要使用某个容器的时候,通常先从docker hub或其它源上下载对应的镜像,然后通过一条命令就可以将...
    wanzhouyi阅读 202评论 0 1