记录一下优化的过程吧,docker build应用有两个痛点,一个时间太长,一个应用太大,浏览了一下相关的文章都是复制黏贴,只能自己动手了。
准备,以下是需要先了解的东西
- docker
- docker buildx 一个新的构建工具
- docker buildkit 一个新的构建引擎
优化.1
拆分为多段构建,示例代码
FROM node:16.19.1-alpine as react_build
WORKDIR /app
COPY . .
RUN npm i
RUN npm build
# 阶段2
FROM alpine:latest
WORKDIR /app
COPY --from=react_build /app/dist ./frontend
优化.2
docker版本需大于18.09
启用buildkit github.com/moby/buildk…
# syntax = docker/dockerfile:experimental
使用run --mount缓存(其余请自行查阅文档)
| Option | Description |
|---|---|
id | id 设置一个标志,以便区分缓存。 |
target (必填项) | 缓存的挂载目标文件夹。 |
ro,readonly | 只读,缓存文件夹不能被写入。 |
sharing | 有 shared private locked 值可供选择。sharing 设置当一个缓存被多次使用时的表现,由于 BuildKit 支持并行构建,当多个步骤使用同一缓存时(同一 id)会发生冲突。shared 表示多个步骤可以同时读写,private 表示当多个步骤使用同一缓存时,每个步骤使用不同的缓存,locked 表示当一个步骤完成释放缓存后,后一个步骤才能继续使用该缓存。 |
from | 缓存来源(构建阶段),不填写时为空文件夹。 |
source | 来源的文件夹路径。 |
RUN --mount=type=cache,target=/app/node_modules,id=neteasep_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npm.taobao.org
使用docker buildx build代替docker build(mac desktop自带了无需开启特性,其他平台需要手动开启)
优化.3
在最后的步骤尽可能使用小的镜像
如
FROM scratch
如
FROM alpine:latest
具体用什么镜像自行选择
最终运行的效果
10s内完成,构建的任务是并发进行的
备注:初次构建的时间可能会长一点,但也会比优化前节省一半以上的时间。
初始包在1.2GB左右
完整代码
# syntax = docker/dockerfile:experimental
# 第一阶段:构建 React 前端
FROM node:16.19.1-alpine as react_build
WORKDIR /app
COPY ui/package*.json ./
RUN --mount=type=cache,target=/app/node_modules,id=neteasep_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npm.taobao.org
#RUN npm i --registry=https://registry.npm.taobao.org
COPY ui ./
RUN --mount=type=cache,target=/app/node_modules,id=neteasep_app_npm_module,sharing=locked \
npm run build
# 第二阶段:构建 Go 后端
FROM golang:1.20.2 as go_build
WORKDIR /app
COPY go.mod go.sum ./
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go env -w GO111MODULE=on
RUN --mount=type=cache,target=/app/go-build,id=neteasep_app_gobuild,sharing=locked \
go mod download
COPY . ./
RUN --mount=type=cache,target=/app/go-build,id=neteasep_app_gobuild,sharing=locked \
CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o main .
# 第三阶段:生成最终镜像
FROM scratch
WORKDIR /app
COPY --from=react_build /app/dist ./frontend
COPY --from=go_build /app/main .
EXPOSE 7878
ENTRYPOINT ["./main"]