[node.js] Docker가 Dockerfile을 빌드 할 때 RUN npm 설치 지침을 캐시하는 방법

현재 내 애플리케이션을위한 노드 백엔드를 개발 중입니다. 도킹 할 때 ( docker build .) 가장 긴 단계는 RUN npm install. 이 RUN npm install명령은 작은 서버 코드 변경 시마다 실행되므로 빌드 시간이 늘어나 생산성이 저하됩니다.

응용 프로그램 코드가있는 곳에 npm 설치를 실행하고 ADD 명령을 사용하여 컨테이너에 node_modules를 추가하면이 문제가 해결되지만 모범 사례와는 거리가 멀습니다. 그것은 Dockerizing에 대한 전체 아이디어를 깨뜨리고 컨테이너의 무게를 훨씬 더 많이 유발합니다.

다른 해결책이 있습니까?



답변

그래서 도커 파일을 작성할 때 효율성에 관한 이 훌륭한 기사를 찾았습니다 .

다음은 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 설치 명령을 실행하면 코드 변경으로 인해 RUN npm 설치가 트리거되지 않습니다. 지시에 따라 package.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"]

여기서 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/

모든 도커 빌드에서 npm 설치 단계를 피하려면 해당 행을 복사하고 ^ / opt / 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

멋진 튜토리얼 : https://codefresh.io/docker-tutorial/node_docker_multistage/


답변

가장 간단한 접근 방식은 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


답변

이미 알고 계실 것 같지만 같은 폴더에 .dockerignore 파일을 포함시킬 수 있습니다.

node_modules
npm-debug.log

Docker 허브로 푸시 할 때 이미지가 팽창하는 것을 방지하려면


답변

tmp 폴더를 사용할 필요가 없으며 package.json을 컨테이너의 응용 프로그램 폴더에 복사하고 설치 작업을 수행하고 나중에 모든 파일을 복사하십시오.

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


답변