2016-03-03 49 views
32

我目前正在爲我的應用程序開發一個Node後端。當dockerizing它(docker build。)時,最長的階段是RUN npm install。每個小型服務器代碼都會改變RUN npm install指令的符號,通過讓開發人員等待每次完成構建來影響生產力。如何在docker構建Dockerfile時緩存RUN npm install指令

我發現運行npm install應用程序代碼所在的位置,並使用ADD指令將node_modules添加到容器,可以解決此問題,但這遠不是最佳實踐。這種做法違反了碼頭化的整個想法,並導致容器重量增加。

任何其他解決方案?

回答

66

好吧,我在編寫docker文件時發現了效率爲this great article

這是一個壞的搬運工文件運行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指令(一個用於文件的package.json和另一個用於其他文件),並在添加實際代碼之前運行npm install指令,任何代碼更改都不會觸發RUN npm install指令,只有package.json的更改纔會觸發它。更好的做法搬運工文件:

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

這就是的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構建階段只複製這些行並將^/opt/app ^更改爲應用程序在容器中的位置。

+2

工程。但有些觀點。 'ADD'不鼓勵'COPY',afaik。 「COPY」更加有效。國際海事組織,最後兩段沒有必要,因爲它們是重複的,而且從應用程序的角度來看,只要設置了「WORKDIR」,那麼應用程序所在的文件系統上的位置就不重要了。 – eljefedelrodeodeljefe

+2

更好的是將所有的apt-get命令合併到一個RUN中,包括一個'apt-get clean'。另外,將./node_modules添加到.dockerignore中,以避免將工作目錄複製到構建的容器中,並加快構建的構建上下文複製步驟。 – Symmetric

+0

爲什麼在單獨的RUN中執行復制命令?如果我移動node_modules包而不是複製它,這有什麼關係嗎?因爲它可能會相對較大,具體取決於您安裝的數量。 –

2

我想你可能已經知道,但你可以包括含

node_modules 
npm-debug.log 

,以避免腹脹你的形象,當你推到泊塢窗樞紐同一文件夾中的文件.dockerignore

5

我發現最簡單的方法是利用Docker的複製語義:

COPY指令從路徑中的容器的文件系統複製新文件或目錄並將它們添加到容器的文件系統。

這意味着,如果你第一次明確地複製package.json文件,然後運行npm install一步,它可以被緩存,然後你可以複製源目錄中的其餘部分。如果package.json文件已更改,那麼這將是新的,它將重新運行npm安裝緩存以供將來構建。

一個從Dockerfile結束片斷會是什麼樣子:

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

# install application 
COPY . /usr/app 
相關問題