Ok, então encontrei este ótimo artigo sobre eficiência ao escrever um arquivo docker.
Este é um exemplo de arquivo docker inválido adicionando o código do aplicativo antes de executar a RUN npm install
instrução:
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"]
Dividindo a cópia do aplicativo em 2 instruções COPY (uma para o arquivo package.json e outra para o restante dos arquivos) e executando a instrução de instalação do npm antes de adicionar o código real, qualquer alteração de código não acionará a instalação RUN do npm instrução, apenas alterações do package.json irão acioná-lo. Arquivo docker de prática recomendada:
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"]
É aqui que o arquivo package.json adicionado, instale suas dependências e copie-as para o contêiner WORKDIR, onde o aplicativo reside:
ADD package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app/
Para evitar a fase de instalação do npm em cada build do docker, apenas copie essas linhas e altere ^ / opt / app ^ para o local em que seu aplicativo está dentro do contêiner.
ADD
é desencorajado em favor deCOPY
, afaik.COPY
é ainda mais eficaz. IMO, os dois últimos parágrafos não são necessários, uma vez que são duplicados e também do ponto de vista do app não importa onde no sistema de arquivos o app está, desde queWORKDIR
esteja configurado.apt-get clean
. Além disso, adicione ./node_modules ao seu .dockerignore, para evitar copiar seu diretório de trabalho em seu contêiner construído e para acelerar a etapa de cópia do contexto de construção da construção.package.json
à posição de repouso final, também funciona bem (eliminando qualquer cp / mv).Esquisito! Ninguém menciona a construção em vários estágios .
# ---- 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 incrível aqui: https://codefresh.io/docker-tutorial/node_docker_multistage/
fonte
COPY
declaração depoisENTRYPOINT
?Descobri que a abordagem mais simples é aproveitar a semântica de cópia do Docker:
Isso significa que se você primeiro copiar explicitamente o
package.json
arquivo e depois executar anpm install
etapa, ele poderá ser armazenado em cache e, em seguida, poderá copiar o restante do diretório de origem. Se opackage.json
arquivo foi alterado, isso será novo e executará novamente o cache de instalação do npm para compilações futuras.Um snippet do final de um Dockerfile ficaria assim:
fonte
cd /usr/app
você pode / deve usarWORKDIR /usr/app
./usr/app
dentro da imagem que criará um/usr/app/node_modules
com dependências instaladas da instalação do npm.COPY . /usr/app
copiaria opackage.json
arquivo novamente/usr/app
com o resto dos arquivos?Imagino que você já saiba, mas poderia incluir um arquivo .dockerignore na mesma pasta contendo
para evitar o inchaço de sua imagem ao empurrar para o hub do docker
fonte
você não precisa usar a pasta tmp, apenas copie o package.json para a pasta do aplicativo do seu contêiner, faça algum trabalho de instalação e copie todos os arquivos mais tarde.
fonte