जब Dockerfile का निर्माण करते हैं तो RUN npm इंस्टाल इंस्टाल करें


86

मैं वर्तमान में अपने आवेदन के लिए एक नोड बैकएंड विकसित कर रहा हूं। इसे कब करना ( docker build .) सबसे लंबा चरण है RUN npm installRUN npm installवृद्धि की निर्माण समय के माध्यम से हर छोटे सर्वर कोड परिवर्तन पर शिक्षा रन है, जो बाधा उत्पन्न उत्पादकता।

मैंने पाया कि एनपीएम इंस्टॉल करना जहां एप्लिकेशन कोड रहता है और एडीडी निर्देश के साथ कंटेनर में नोड_मॉड्यूल्स को जोड़ना इस मुद्दे को हल करता है, लेकिन यह सबसे अच्छा अभ्यास से दूर है। यह डॉकटराइज करने के पूरे विचार को तोड़ता है और यह कंटेनर को अधिक वजन का कारण बनाता है।

कोई और उपाय?

जवाबों:


124

ठीक है, इसलिए मुझे एक डॉक फ़ाइल लिखते समय दक्षता के बारे में यह शानदार लेख मिला ।

यह RUN npm installनिर्देश चलाने से पहले एप्लिकेशन कोड को जोड़ने वाली एक खराब डॉक फ़ाइल का एक उदाहरण है :

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 निर्देशों (पैकेज के लिए एक .json फ़ाइल और बाकी फाइलों के लिए अन्य) में विभाजित करके और वास्तविक कोड जोड़ने से पहले npm इंस्टॉल निर्देश चलाने के लिए, कोई भी कोड परिवर्तन नहीं होगा RUN npm स्थापित ट्रिगर निर्देश, केवल 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 ^ को उस स्थान पर बदलें जहाँ आपका ऐप कंटेनर के अंदर रहता है।


2
यह काम करता है। कुछ बिंदु हालांकि। ADDके पक्ष में हतोत्साहित किया जाता है COPY, afaik। COPYऔर भी प्रभावी है। IMO, अंतिम दो पैराग्राफ आवश्यक नहीं हैं, क्योंकि वे डुप्लिकेट होते हैं और ऐप के दृष्टिकोण से भी यह कोई फर्क नहीं पड़ता कि फाइल सिस्टम पर वह ऐप कहां रहता है, जब तक कि WORKDIRसेट है।
eljefedelrodeodeljefe

2
बेहतर-अभी भी सभी आरयूएन को एक आरयूएन पर प्राप्त करना है, जिसमें एक भी शामिल है apt-get clean। इसके अलावा, अपने .dockerignore में/node_modules जोड़ें, अपने काम करने वाले डायरेक्टरी को अपने निर्मित कंटेनर में कॉपी करने से बचें, और बिल्ड-बिल्ड कॉपी-बिल्ड चरण की गति बढ़ाने के लिए।
सिमेट्रिक

1
एक ही दृष्टिकोण लेकिन सिर्फ package.jsonअंतिम आराम की स्थिति में जोड़ना ठीक काम करता है (किसी भी सीपी / एमवी को नष्ट करना)।
जे। फ्रिट्ज़ बार्न्स

27
मुझे नहीं मिला। आप एक अस्थायी निर्देशिका में क्यों स्थापित करते हैं और फिर इसे ऐप निर्देशिका में स्थानांतरित करते हैं? सिर्फ ऐप डायरेक्टरी में इंस्टॉल क्यों नहीं? मुझे यहां क्या समझ नहीं आ रहा है?
जोनिबा

1
यह शायद मर चुका है, लेकिन मैंने भविष्य के पाठकों के लिए इसका उल्लेख किया। @ जोनिबा ऐसा करने का एक कारण स्थानीय होस्ट फ़ाइल सिस्टम के नोड_मॉड्यूल्स के साथ हस्तक्षेप किए बिना अस्थायी फ़ोल्डर के रूप में अस्थायी फ़ोल्डर को माउंट करना होगा। यानी मैं अपने ऐप को स्थानीय रूप से चलाना चाहता हूं, लेकिन एक कंटेनर में भी और अभी भी अपने नोड_मॉड्यूल रखने की क्षमता रखता है जब पैकेज को लगातार दोबारा डाउनलोड नहीं किया जाता है।
आगजनी

41

अजीब! बहु मंच निर्माण का कोई उल्लेख नहीं करता है ।

# ---- 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
एक COPYबयान के बाद ENTRYPOINTक्या हो रहा है ?
lindhe

महान, यह भी एक अच्छा लाभ प्रदान करते हैं जब आप अपने डॉकरफाइल का परीक्षण कर रहे हों तो बिना किसी निर्भरता के बिना हर बार जब आप अपने डॉकरीफाइल को संपादित करते हैं
जेवियर ब्रासॉड

30

मैंने पाया है कि सबसे आसान तरीका डॉकटर की कॉपी शब्दार्थ का लाभ उठाना है:

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

6
के बजाय cd /usr/appआप कर सकते हैं / का उपयोग करना चाहिए WORKDIR /usr/app
व्लादिमीर वुकानैक

1
@ व्लादिमीरवुकनाक: +1: कार्यदिवस का उपयोग करने पर; मैंने ऊपर दिए गए उत्तर को अपडेट कर दिया है।
जे। फ्रिट्ज़ बार्न्स

npm स्थापित / usr / अनुप्रयोग निर्देशिका में चलाने के लिए या है। ?
user557657 19

1
@ user557657 WORKDIR भविष्य की छवि के भीतर निर्देशिका सेट करता है जिसमें से कमांड चलाया जाएगा। तो इस मामले में, यह /usr/appछवि के भीतर से npm इंस्टॉल चल रहा है जो npm इंस्टॉल से /usr/app/node_modulesस्थापित निर्भरता के साथ होगा ।
जे। फ्रिट्ज़ बार्न्स

1
@ J.FritzBarnes बहुत बहुत धन्यवाद। फाइल को बाकी फाइलों के साथ फिर से COPY . /usr/appकॉपी नहीं करेगा ? package.json/usr/app
15:55 बजे user557657

3

मुझे लगता है कि आप पहले से ही जानते होंगे, लेकिन आप एक ही फ़ोल्डर में एक .dockerignore फ़ाइल शामिल कर सकते हैं

node_modules
npm-debug.log

जब आप डॉकटर हब को धक्का देते हैं तो अपनी छवि को फुलाने से बचें


1

आपको tmp फ़ोल्डर का उपयोग करने की आवश्यकता नहीं है, बस पैकेज को कॉपी करें। अपने कंटेनर के एप्लिकेशन फ़ोल्डर में जाएं, कुछ काम करें और बाद में सभी फ़ाइलों को कॉपी करें।

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

इसलिए आप कंटेनर डायरेक्टरी / ऑप्ट / ऐप में npm इंस्टाल कर रहे हैं और फिर लोकल मशीन से सभी फाइलों को कॉपी / ऑप्ट / ऐप में कॉपी कर रहे हैं?
user557657
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.