Ok, więc znalazłem ten świetny artykuł o wydajności podczas pisania pliku dockera.
Oto przykład złego pliku dockera, który dodaje kod aplikacji przed uruchomieniem RUN npm install
instrukcji:
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ę aplikacji na 2 instrukcje COPY (jedną dla pliku package.json, a drugą dla pozostałych plików) i uruchamiając instrukcję instalacji npm przed dodaniem właściwego kodu, żadna zmiana kodu nie wywoła instalacji RUN npm instrukcji, tylko zmiany w pliku package.json będą ją wywoływać. Lepsze praktyki w pliku dockera:
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"]
W tym miejscu dodano plik package.json, zainstaluj jego zależności i skopiuj je do kontenera WORKDIR, w którym znajduje się aplikacja:
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ąć fazy instalacji npm w każdej kompilacji platformy Docker, po prostu skopiuj te wiersze i zmień ^ / opt / app ^ na lokalizację, w której znajduje się Twoja aplikacja w kontenerze.
ADD
jest odradzany na korzyśćCOPY
, afaik.COPY
jest jeszcze bardziej skuteczny. IMO, ostatnie dwa 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, o ileWORKDIR
jest ustawiona.apt-get clean
. Dodaj również ./node_modules do swojego .dockerignore, aby uniknąć kopiowania katalogu roboczego do zbudowanego kontenera i przyspieszyć krok tworzenia kopii kontekstowej kompilacji.package.json
do końcowej pozycji spoczynkowej również działa dobrze (eliminując wszelkie cp / mv).Dziwne! Nikt nie wspomina o budowie wieloetapowej .
# ---- 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
Niesamowite tuto tutaj: https://codefresh.io/docker-tutorial/node_docker_multistage/
źródło
COPY
oświadczenia poENTRYPOINT
?Odkryłem, że najprostszym podejściem jest wykorzystanie semantyki kopiowania Dockera:
Oznacza to, że jeśli najpierw jawnie skopiujesz
package.json
plik, a następnie uruchomisznpm install
krok, aby można go było buforować, a następnie możesz skopiować resztę katalogu źródłowego. Jeślipackage.json
plik się zmienił, to będzie nowy i ponownie uruchomi buforowanie instalacji npm, które będzie używane w przyszłych kompilacjach.Fragment z końca pliku Dockerfile wyglądałby tak:
źródło
cd /usr/app
możesz / powinieneś użyćWORKDIR /usr/app
./usr/app
obrazu, która utworzy/usr/app/node_modules
z zależnościami zainstalowanymi z instalacji npm.COPY . /usr/app
skopiujepackage.json
ponownie pliku razem/usr/app
z pozostałymi plikami?Wyobrażam sobie, że możesz już wiedzieć, ale możesz dołączyć plik .dockerignore do tego samego folderu zawierającego
aby uniknąć rozdęcia obrazu podczas wypychania do centrum Docker
źródło
nie musisz używać folderu tmp, po prostu skopiuj plik package.json do folderu aplikacji swojego kontenera, przeprowadź instalację i skopiuj wszystkie pliki później.
źródło