多阶段 Dockerfile 导致 运行 出 space
Multi stage Dockerfile leads to running out of space
由于我的代码(nodeJS 应用程序)比(npm)依赖项更改得更频繁,我尝试在我的 CI.
中构建类似缓存的东西
我正在使用多阶段 Dockerfile。在那里,我 运行 npm install 用于所有且仅用于产品依赖项。后来它们被复制到最终图像中,因此它要小得多。太好了。
如果没有更改依赖项,构建速度也会非常快。
但是,随着时间的推移,硬盘会变满,所以我必须 运行 docker prune ...
才能取回 space。但是,当我这样做时,缓存消失了。
因此,如果我 运行 在我的 CI 中的每个管道之后 prune
,我不会得到多阶段 Dockerfile 的 'cache functionality'。
### 1. Build
FROM node:10.13 AS build
WORKDIR /home/node/app
COPY ./package*.json ./
COPY ./.babelrc ./
RUN npm set progress=false \
&& npm config set depth 0 \
&& npm install --only=production --silent \
&& cp -R node_modules prod_node_modules
RUN npm install --silent
COPY ./src ./src
RUN ./node_modules/.bin/babel ./src/ -d ./dist/ --copy-files
### 2. Run
FROM node:10.13-alpine
RUN apk --no-cache add --virtual \
builds-deps \
build-base \
python
WORKDIR /home/node/app
COPY --from=build /home/node/app/prod_node_modules ./node_modules
COPY --from=build /home/node/app/dist .
EXPOSE 3000
ENV NODE_ENV production
CMD ["node", "app.js"]
如果您的 CI 系统允许您有多个 docker build
步骤,您可以将其拆分为两个 Dockerfile。
# Dockerfile.dependencies
# docker build -f Dockerfile.dependencies -t me/dependencies .
FROM node:10.13
...
RUN npm install
# Dockerfile
# docker build -t me/application .
FROM me/dependencies:latest AS build
COPY ./src ./src
RUN ./node_modules/.bin/babel ./src/ -d ./dist/ --copy-files
FROM node:10.13-alpine
...
CMD ["node", "app.js"]
如果您这样做,那么您可以在每次构建后 delete unused images:
docker image prune
依赖项映像的最新版本会有一个标签,因此它不会是 "dangling",也不会出现在映像列表中。在每个构建中,它的标签将获得 "taken from" 之前的构建(如果它发生了变化),因此这个序列将清理之前的构建。这也将删除 "build" 图像,但正如您所注意到的,如果 任何东西 更改为触发构建,它可能会在 src
树中并因此强制重建有道理。
在这种特定情况下,只使用 latest
标签是合适的。如果最终构建的图像有一些更独特的标签(例如,基于版本号或时间戳)并且它们堆叠在一起,那么您可能需要对该图像列表进行一些更有创意的过滤以清理它们。
由于我的代码(nodeJS 应用程序)比(npm)依赖项更改得更频繁,我尝试在我的 CI.
中构建类似缓存的东西我正在使用多阶段 Dockerfile。在那里,我 运行 npm install 用于所有且仅用于产品依赖项。后来它们被复制到最终图像中,因此它要小得多。太好了。
如果没有更改依赖项,构建速度也会非常快。
但是,随着时间的推移,硬盘会变满,所以我必须 运行 docker prune ...
才能取回 space。但是,当我这样做时,缓存消失了。
因此,如果我 运行 在我的 CI 中的每个管道之后 prune
,我不会得到多阶段 Dockerfile 的 'cache functionality'。
### 1. Build
FROM node:10.13 AS build
WORKDIR /home/node/app
COPY ./package*.json ./
COPY ./.babelrc ./
RUN npm set progress=false \
&& npm config set depth 0 \
&& npm install --only=production --silent \
&& cp -R node_modules prod_node_modules
RUN npm install --silent
COPY ./src ./src
RUN ./node_modules/.bin/babel ./src/ -d ./dist/ --copy-files
### 2. Run
FROM node:10.13-alpine
RUN apk --no-cache add --virtual \
builds-deps \
build-base \
python
WORKDIR /home/node/app
COPY --from=build /home/node/app/prod_node_modules ./node_modules
COPY --from=build /home/node/app/dist .
EXPOSE 3000
ENV NODE_ENV production
CMD ["node", "app.js"]
如果您的 CI 系统允许您有多个 docker build
步骤,您可以将其拆分为两个 Dockerfile。
# Dockerfile.dependencies
# docker build -f Dockerfile.dependencies -t me/dependencies .
FROM node:10.13
...
RUN npm install
# Dockerfile
# docker build -t me/application .
FROM me/dependencies:latest AS build
COPY ./src ./src
RUN ./node_modules/.bin/babel ./src/ -d ./dist/ --copy-files
FROM node:10.13-alpine
...
CMD ["node", "app.js"]
如果您这样做,那么您可以在每次构建后 delete unused images:
docker image prune
依赖项映像的最新版本会有一个标签,因此它不会是 "dangling",也不会出现在映像列表中。在每个构建中,它的标签将获得 "taken from" 之前的构建(如果它发生了变化),因此这个序列将清理之前的构建。这也将删除 "build" 图像,但正如您所注意到的,如果 任何东西 更改为触发构建,它可能会在 src
树中并因此强制重建有道理。
在这种特定情况下,只使用 latest
标签是合适的。如果最终构建的图像有一些更独特的标签(例如,基于版本号或时间戳)并且它们堆叠在一起,那么您可能需要对该图像列表进行一些更有创意的过滤以清理它们。