本文的原由是在作的一個項目打包時間實在太慢了,所謂代碼5分鐘,打包半小時,又正好在看docker的一些東西,因此打算優化一下這個dockerfilenode
一.首先來看下這個dockerfilegit
image1
鏡像(這裏隨意寫的,舉例而已)做爲compile
鏡像/code
目錄package.json
,yarn.lock
,npmrc
文件到/code
目錄中,用於安裝NPM
模塊yarn install --production
,而且將node_module
拷貝到臨時目錄yarn
/code
目錄中npm run build
來打包項目yarn install --production
之後再運行yarn
,這不是重複了,畫蛇添足嗎package.json
到/code
目錄下,而後再拷貝一遍所有文件呢,這不是也重複了嗎image2
鏡像做爲release
鏡像/code
目錄node_module
client
,config
文件夾yarn start
yarn install --production
是安裝了生產要用的NPM
包,而後拷貝到臨時目錄裏,後面從臨時目錄裏拷貝,拷貝出來的是生產時要用的包,不是所有的包,減小了包的體積package.json
,是由於咱們應該把變化最少的部分放在Dockerfile的前面,這樣能夠充分利用鏡像緩存,詳見 zhuanlan.zhihu.com/p/26904830 中的 11.合理調整COPY與RUN的順序
二.這個dockerfile打包出來的鏡像的大小,能夠看到有725M,中間鏡像有2.11G,真的對得起代碼5分鐘,打包半小時github
三.dive工具分析這個鏡像,(dive 鏡像id),詳見 github.com/wagoodman/d… 能夠看到總共725M,能夠優化的有421Mdocker
四.優化後的dockerfilenpm
我爲何這麼優化json
我沒有先拷貝package.json
等文件並安裝了NPM
包之後再拷貝其餘文件,由於本篇文章中的 zhuanlan.zhihu.com/p/26904830 的合理調整COPY與RUN的順序中寫到的是首先將package.json
拷貝進來,而後安裝包,再將剩餘其餘文件拷貝進指定的目錄,而我這個項目,package.json
之外的文件都要用到,第一次拷貝package.json
等文件之後,第二次拷貝最方便的方法是COPY . /code
,要拷貝其餘文件,而排除package.json
文件的作法反而繁瑣緩存
基於上面那一點的操做的考慮之後,在compile
鏡像中服務器
/code
目錄,/code
目錄下,yarn build
代替npm run build
,而後將yarn
和yarn build
命令合併在release
鏡像中工具
code . /code
,由於和後面的copy --from=compile
那些命令重複了code . /code
之後,鏡像是跑不起來的,由於少了一些文件,package.json
和next.config.js
,運行yarn start
的時候要package.json
文件,而yarn start
命令是NEXT_ENV=prod PORT=3000 next start client
,要next的配置文件我是怎麼知道少了這些文件的優化
docker run --name test -p 4040:3000 5be399174a72
首先先跑起這個鏡像docker ps -a
找出容器docker exec -it c57cb2999203 /bin/sh
進入到容器中查看,能夠看到/code
目錄中有這些文件,對比起先能夠跑起來的容器裏面的文件和跑不起來的容器的報錯,排查出少了哪些文件,須要哪些文件根據問題1的解答,我爲何不用yarn install --production
了,由於只用這些包,yarn start
命令是跑不起來的,並且從下面的dive工具顯示,能夠優化的已經只有358K了,也就沒有必要運行這個命令再拷貝到臨時目錄了,畢竟後面也還要運行yarn
五.能夠看到如今鏡像只有489M的,中間鏡像compile
也變少了,只有1.71G
六.再用dive工具查看這個鏡像,發現總共489M,能夠優化的只有358K了
七. 優化升級.dockerignore
node_module
包傳到docker服務器上.dockerignore
之後,傳到docker服務器上的大小從343M減到了29M八.爲何這個dockerfile跑不起來
node_module
,因此這個dockerfile在最初的dockerfile上加了一句RUN /bin/rm -fr node_modules
yarn start
的時候要用到node_module
,因此在前面刪了node_module
會跑不起來