我目前正在为我的应用程序开发一个Node后端。对其进行dockering时(docker build.
)最长的阶段是RUN npm install
。RUN npm install
指令在每次小的服务器代码更改上都运行,这会通过增加构建时间来阻碍生产力。
我发现在应用程序代码所在的位置运行npm install并使用ADD指令将node_modules添加到容器中解决了这个问题,但这远非最佳实践。它打破了对其进行docker化的整个想法,并导致容器的重量增加。
还有其他解决办法吗?
好的,所以我发现了这篇关于编写docker文件时效率的好文章。
这是在运行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指令(一条用于pack. json文件,另一条用于其余文件),并在添加实际代码之前运行npm install指令,任何代码更改都不会触发RUN npm install指令,只有pack.json的更改才会触发它。更好的练习docker文件:
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"]
这是添加pack. 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安装阶段,只需复制这些行并将^/select/app^更改为您的应用程序在容器中的位置。
奇怪!没有人提到多阶段构建。
# ---- 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/
我发现最简单的方法是利用Docker的复制语义学:
COPY指令从复制新文件或目录并将它们添加到路径处容器的文件系统中。
这意味着,如果您首先显式复制pack. json
文件,然后运行npm install
步骤,它可以被缓存,然后您可以复制源目录的其余部分。如果pack.json
文件发生了变化,那么这将是新的,它将重新运行npm安装缓存,用于未来的构建。
Dockerfile末尾的片段如下所示:
# install node modules
WORKDIR /usr/app
COPY package.json /usr/app/package.json
RUN npm install
# install application
COPY . /usr/app