如何在docker构建Dockerfile时缓存RUN npm安装指令

时间:2016-03-03 14:19:55

标签: node.js docker dockerfile

我目前正在为我的应用程序开发一个Node后端。 对它进行对等化(docker build。)时,最长的阶段是#include <omp.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { int nthreads, tid; /* Fork a team of threads giving them their own copies of variables */ static #pragma omp parallel private(nthreads, tid) //I tried it here { /* Obtain thread number */ tid = omp_get_thread_num(); printf("Hello World from thread = %d\n", tid); /* Only master thread does this */ if (tid == 0) { nthreads = omp_get_num_threads(); printf("Number of threads = %d\n", nthreads); } } /* All threads join master thread and disband */ } 。每个小型服务器代码上的RUN npm install指令都会发生变化,通过让开发人员每次等待构建完成来影响生产力。

我发现运行应用程序代码所在的npm install并使用ADD指令将node_modules添加到容器中解决了这个问题, 但它远非最佳做法。它打破了它的整个想法,它使容器重量更大。

还有其他解决方案吗?

5 个答案:

答案 0 :(得分:96)

好的,所以我在编写docker文件时找到了this great article关于效率的信息。

这是在运行RUN npm install指令之前添加应用程序代码的错误docker文件的示例:

FROM ubuntu

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y install python-software-properties git build-essential
RUN add-apt-repository -y ppa:chris-lea/node.js
RUN apt-get update
RUN apt-get -y install nodejs

WORKDIR /opt/app

COPY . /opt/app
RUN npm install
EXPOSE 3001

CMD ["node", "server.js"]

通过将应用程序的副本分为2个COPY指令(一个用于package.json文件,另一个用于其余文件)并在添加实际代码之前运行npm install指令,任何代码更改都不会触发运行npm install指令,只有package.json的更改才会触发它。更好地练习泊坞文件:

FROM ubuntu
MAINTAINER David Weinstein <david@bitjudo.com>

# install our dependencies and nodejs
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y install python-software-properties git build-essential
RUN add-apt-repository -y ppa:chris-lea/node.js
RUN apt-get update
RUN apt-get -y install nodejs

# use changes to package.json to force Docker not to use the cache
# when we change our application's nodejs dependencies:
COPY package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app/

# From here we load our application's code in, therefore the previous docker
# "layer" thats been cached will be used if possible
WORKDIR /opt/app
COPY . /opt/app

EXPOSE 3000

CMD ["node", "server.js"]

这是添加package.json文件的位置,安装其依赖项并将它们复制到应用程序所在的容器WORKDIR中:

ADD package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app/

要避免每个docker构建的npm安装阶段,只需复制这些行并将^ / opt / app ^更改为应用程序位于容器内的位置。

答案 1 :(得分:20)

奇怪!没有人提到多阶段构建

# ---- Base Node ----
FROM alpine:3.5 AS base
# install node
RUN apk add --no-cache nodejs-current tini
# set working directory
WORKDIR /root/chat
# Set tini as entrypoint
ENTRYPOINT ["/sbin/tini", "--"]
# copy project file
COPY package.json .

#
# ---- Dependencies ----
FROM base AS dependencies
# install node packages
RUN npm set progress=false && npm config set depth 0
RUN npm install --only=production 
# copy production node_modules aside
RUN cp -R node_modules prod_node_modules
# install ALL node_modules, including 'devDependencies'
RUN npm install

#
# ---- Test ----
# run linters, setup and tests
FROM dependencies AS test
COPY . .
RUN  npm run lint && npm run setup && npm run test

#
# ---- Release ----
FROM base AS release
# copy production node_modules
COPY --from=dependencies /root/chat/prod_node_modules ./node_modules
# copy app sources
COPY . .
# expose port and define CMD
EXPOSE 5000
CMD npm run start

这里有令人敬畏的tuto:https://codefresh.io/docker-tutorial/node_docker_multistage/

答案 2 :(得分:16)

我发现最简单的方法是利用Docker的复制语义:

  

COPY指令从中复制新文件或目录,并将它们添加到路径中容器的文件系统中。

这意味着如果您首先显式复制package.json文件,然后运行可以缓存的npm install步骤,那么您可以复制源目录的其余部分。如果package.json文件已更改,那么这将是新的,它将重新运行npm安装缓存,以便将来构建。

Dockerfile末尾的片段如下所示:

# install node modules
WORKDIR  /usr/app
COPY     package.json /usr/app/package.json
RUN      npm install

# install application
COPY     . /usr/app

答案 3 :(得分:5)

我想你可能已经知道,但你可以在包含

的同一个文件夹中包含.dockerignore文件
node_modules
npm-debug.log

以避免在推送到docker hub

时使图像膨胀

答案 4 :(得分:1)

您不需要使用tmp文件夹,只需将package.json复制到容器的应用程序文件夹,进行一些安装工作,然后再复制所有文件。

COPY app/package.json /opt/app/package.json
RUN cd /opt/app && npm install
COPY app /opt/app