非多阶段
以node项目为例:
FROM alpine
RUN mkdir -p /opt/app
WORKDIR /opt/app
COPY package.json package-lock.json ./
RUN apk add --no-cache --update nodejs npm
RUN apk add --no-cache \
gcc \
g++ \
python3=3.10.10-r0 \
make=4.3-r1 \
pkgconf
COPY . .
RUN npm install --production
EXPOSE 8080
CMD ["node", "main.js"]
这样虽然可以使用,但是很多依赖是生产环境下不需要受用的,比如build阶段的gcc以及npm等等
多阶段构建
doc: 多阶段构建 (docker.com)
在Docker 17.05版本以后,就可以使用Multi-stage builds(多阶段构建)
FROM alpine AS builder
RUN mkdir -p /opt/app
WORKDIR /opt/app
COPY package.json package-lock.json ./
RUN apk add --no-cache --update nodejs npm
RUN apk add --no-cache \
gcc \
g++ \
python3=3.10.10-r0 \
make=4.3-r1 \
pkgconf
RUN npm install --production
FROM alpine
RUN mkdir -p /opt/app
WORKDIR /opt/app
RUN apk add --no-cache --update nodejs
COPY --from=builder /opt/app/node_modules ./node_modules
COPY . .
EXPOSE 8080
CMD ["node", "main.js"]
将build与实际运行环境剥离出来了,第一个阶段作为builder,将node依赖install好,生成node_modules,然后在实际运行容器中COPY --from=builder /opt/app/node_modules ./node_modules将依赖复制进来,这样各种编译依赖就会被舍弃,npm也不用出现在运行环境中,减少了包体积
这样做的好处不止是减少包体积,在其他项目中还可以隐藏源代码,生产环境只有编译好的可执行文件。