2016-03-03 8 views
32

Obecnie rozwijam backend węzła dla mojej aplikacji. Po dokowaniu (budowanie dockera.) Najdłuższą fazą jest RUN npm install. Instrukcja RUN npm install uruchamia się przy każdej zmianie małego kodu serwera, wpływając na wydajność, powodując, że programista czeka na zakończenie kompilacji za każdym razem.Jak cacheować instrukcję instalacji npm RUN, kiedy doker buduje plik Dockerfilka

Znalazłem, że uruchomienie npm install, gdzie kod aplikacji żyje i dodanie modułu node_modules do kontenera z instrukcją ADD rozwiązuje ten problem, , ale daleko mu do najlepszej praktyki. To łamie cały pomysł dokowania go i powoduje, że pojemnik waży znacznie więcej.

Jakieś inne rozwiązanie?

Odpowiedz

66

Ok, więc znalazłem this great article o skuteczności przy pisaniu pliku dokowanego.

Jest to przykład złego pliku Döcker dodanie kodu aplikacji przed uruchomieniem instrukcji 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"] 

Dzieląc kopię wniosku na 2 instrukcji Copy (jeden dla pliku package.json i drugi dla pozostałych plików) i uruchomienie instrukcji instalacji npm przed dodaniem aktualnego kodu, zmiana kodu nie spowoduje uruchomienia instrukcji instalacji npm, tylko zmiany w pakiecie.json uruchomią ją. Lepsza plik praktyka doker:

FROM ubuntu 
MAINTAINER David Weinstein <[email protected]> 

# 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"] 

To gdzie plik package.json dodał zainstalować jego zależności i skopiować je do WORKDIR pojemnika, gdzie aplikacja mieszka:

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

Aby uniknąć zainstalowania npm faza na każdej kompilacji dokowania po prostu skopiuj te linie i zmień ^/opt/app^na lokalizację, w której znajduje się aplikacja wewnątrz kontenera.

+2

to działa. Niektóre punkty jednak. 'ADD' jest odradzane na rzecz' COPY', afaik. 'COPY' jest jeszcze bardziej efektywny.IMO, dwa ostatnie akapity nie są konieczne, ponieważ są duplikatami, a także z punktu widzenia aplikacji nie ma znaczenia, gdzie w systemie plików znajduje się aplikacja, pod warunkiem, że ustawione jest 'WORKDIR'. – eljefedelrodeodeljefe

+2

Better-still to połączenie wszystkich komend apt-get w jeden RUN, w tym 'apt-get clean'. Dodaj także ./node_modules do pliku .dockerignore, aby uniknąć kopiowania katalogu roboczego do zbudowanego kontenera i przyspieszenia kroku kompilacji kontekstu kompilacji. – Symmetric

+0

Z jakiego powodu wykonujesz polecenie kopiowania w oddzielnym URUCHOMIENIU? I ma to znaczenie, jeśli przeniesię pakiet node_modules zamiast go skopiować? Ponieważ może on być stosunkowo duży w zależności od tego, jak dużo zainstalujesz –

2

sobie wyobrazić, może już wie, ale można dołączyć plik .dockerignore w tym samym folderze zawierającym

node_modules 
npm-debug.log 

aby uniknąć wzdęcia obraz po naciśnięciu do dokowanym piastę

5

Znalazłem że najprostszym podejściem jest wykorzystanie semantyki kopii Dockera:

Instrukcja KOPIU kopiuje nowe pliki lub katalogi i dodaje je do systemu plików kontenera na ścieżce.

To oznacza, że ​​jeśli najpierw jawnie skopiować plik package.json a następnie uruchomić krok npm install że może być buforowane, a następnie można skopiować resztę katalogu źródłowego. Jeśli plik package.json został zmieniony, to będzie on nowy i ponownie uruchom buforowanie instalacji npm, które będzie używane w przyszłych wersjach.

fragment od końca Dockerfile wyglądałby następująco:

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

# install application 
COPY . /usr/app 
Powiązane problemy