我接受了我目前的一个项目,基本上运行了你的dockerfile…得到了1.1 GB
docker save
焦油文件。它压缩得很好,但是345MB gzip tar文件仍然不是您想要的。”使用阿尔卑斯山的基本图像“有点帮助,但不是银弹;将其切换为
FROM node:8-alpine
减少到514 MB未压缩的tar文件。
如果你还没有
.dockerignore
文件,然后整个现有文件
node_modules
目录将被复制到映像中。(尤其是
COPY . .
步骤将复制整个工作树,覆盖上一步骤中安装的模块。)它只能包含单行
node_modules
阿尔卑斯山的基础图像,加上不发射复制品
节点模块
树,让我降到382 MB未压缩。
请注意,在您的示例中,
npm install
步骤包括所有开发依赖项以及运行时依赖项。这可能是一个巨大的成本。如果您的应用程序不需要任何预编译(节点可以直接运行的是普通的javascript),那么您可以添加它
--only=production
旗子会有帮助的。
如果您确实需要某种程度的预编译(babel、webpack、typescript,…),那么您需要一个多阶段的构建。我实际的dockerfile有三个阶段。首先进行编译,并生成
dist
带有可运行javascript的目录。第二个产生
节点模块
运行时需要的树。第三个(因为我们在这里计算字节数)只复制前两个阶段真正需要的部分。
总数如下:
FROM node:8-alpine AS build
WORKDIR /usr/src/app
# Installing dependencies first can save time on rebuilds
# We do need the full (dev) dependencies here
COPY package.json yarn.lock ./
RUN yarn install
# Then copy in the actual sources we need and build
COPY tsconfig.json ./
COPY src/ ./src/
RUN yarn build
FROM node:8-alpine AS deps
WORKDIR /usr/src/app
# This _only_ builds a runtime node_modules tree.
# We won't need the package.json to actually run the application.
# If you needed developer-oriented tools to do this install they'd
# be isolated to this stage.
COPY package.json yarn.lock ./
RUN yarn install --production
FROM node:8-alpine
WORKDIR /usr/src/app
COPY --from=deps /usr/src/app/node_modules ./node_modules/
COPY --from=build /usr/src/app/dist ./dist/
EXPOSE 3000
CMD ["node", "dist/index.js"]
码头工人储蓄
在此基础上生成一个108 MB的未压缩tar文件。
你会注意到一件事,如果你
docker save node:8-alpine
,该图像本身就是71MB。当你
码头工人储蓄
你每次都被迫复制,当你
docker load
每次你都会得到一份不同的副本。解决这个问题的唯一方法是拥有某种类型的注册服务器(Docker Hub,一个云托管的东西,如Google GCR或AWS ECR,你自己运行的东西),以及
docker push
和
docker pull
从那里。
结果是
node:8
图像是
巨大的
;它的一半大小是一个完整的C工具链(单个层仅为320 MB)(尝试运行
docker history node:8
)这个
standard node image
也有
node:8-slim
它仍然是基于Debian的变体(比阿尔卑斯山的图像大),但更整齐。我得到了221 MB
码头工人储蓄
tar文件将我的dockerfile调整为基于此图像。(如果你
码头工人拉
它将获得一次基本节点运行时,但是如果
码头装载
你会一次又一次地得到它。)