一次Dockerfile優(yōu)化

Dockerfile優(yōu)化

本文的起因是在做的一個項目打包時間實在太慢了,所謂代碼5分鐘,打包半小時,又正好在看docker的一些東西,所以打算優(yōu)化一下這個dockerfile

文前

一.首先來看下這個dockerfile


dockerfile.png
  • 首先將一個image1鏡像(這里隨意寫的,舉例而已)作為compile鏡像
  • 指定了/code目錄
  • 拷貝了本地的package.json,yarn.lock,npmrc文件到/code目錄中,用于安裝NPM模塊
  • 運行了yarn install --production,并且將node_module拷貝到臨時目錄
  • 再運行yarn
  • 在拷貝所有文件到/code目錄中
  • 運行npm run build來打包項目
  • 到這里先提出兩個問題
    • 問題1:為什么要運行了yarn install --production以后再運行yarn,這不是重復了,多此一舉嗎
    • 問題2:為什么要拷貝了package.json/code目錄下,然后再拷貝一遍全部文件呢,這不是也重復了嗎
  • 然后將image2鏡像作為release鏡像
  • 將本地的文件拷貝到當前鏡像中
  • 指定/code目錄
  • 從上一層鏡像臨時目錄中中拷貝node_module
  • 從上一層鏡像中client,config文件夾
  • 運行yarn start
  • 解決問題
    • 問題1:當時沒想通,后來突然想通了,運行了yarn install --production是安裝了生產要用的NPM包,然后拷貝到臨時目錄里,后面從臨時目錄里拷貝,拷貝出來的是生產時要用的包,不是全部的包,減少了包的體積
    • 問題2:為什么要先拷貝package.json,是因為我們應該把變化最少的部分放在Dockerfile的前面,這樣可以充分利用鏡像緩存,詳見https://zhuanlan.zhihu.com/p/26904830中的 11.合理調整COPY與RUN的順序

二.這個dockerfile打包出來的鏡像的大小,可以看到有725M,中間鏡像有2.11G,真的對得起代碼5分鐘,打包半小時

size.png

三.dive工具分析這個鏡像,(dive 鏡像id),詳見https://github.com/wagoodman/dive, 可以看到總共725M,可以優(yōu)化的有421M

dive.png

四.優(yōu)化后的dockerfile

dockerfile.png
  • 我為什么這么優(yōu)化

  • 我沒有先拷貝package.json等文件并安裝了NPM包以后再拷貝其他文件,因為本篇文章中的 https://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,然后將yarnyarn build命令合并
  • release鏡像中

    • 去掉code . /code,因為和后面的copy --from=compile那些命令重復了
    • 去掉code . /code以后,鏡像是跑不起來的,因為少了一些文件,package.jsonnext.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工具顯示,可以優(yōu)化的已經只有358K了,也就沒有必要運行這個命令再拷貝到臨時目錄了,畢竟后面也還要運行yarn

    exec.png

五.可以看到現在鏡像只有489M的,中間鏡像compile也變少了,只有1.71G

size.png

六.再用dive工具查看這個鏡像,發(fā)現總共489M,可以優(yōu)化的只有358K了

dive.png

七. 優(yōu)化升級.dockerignore

  • 因為我們會用yarn重新,所以沒有必要將本地的node_module包傳到docker服務器上
  • 可以看到,設置.dockerignore以后,傳到docker服務器上的大小從343M減到了29M
upload.png
upload.png

八.為什么這個dockerfile跑不起來

  • 因為根據dive工具分析出了是node_module,所以這個dockerfile在最初的dockerfile上加了一句RUN /bin/rm -fr node_modules
  • 前面說到了,yarn start的時候要用到node_module,所以在前面刪了node_module會跑不起來
why.png
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 鏡像的定制實際上就是定制鏡像的每一層所添加的配置、文件等信息,實際上當我們在一個容器中添加或者修改了一些文件后,我...
    wangfs閱讀 426評論 0 0
  • 前端工程化代碼一般通過 包(package) (或者稱為 模塊(module)) 的方式來共享,因此你可以通過它...
    January丶緣閱讀 1,284評論 0 0
  • 寫在最前 1356的錯誤,在前幾天寫的mysqldump問題集合里面已經寫過了,然而本次按照常規(guī)的套路無法處理這次...
    飛翔的Tallgeese閱讀 2,736評論 0 0
  • 關燈睡覺的人兒,突然想到還沒完成今天的簡書。 今天杭州下雪,因為連續(xù)的下雨,所以沒有積起來,中間貌似還夾雜過一些小...
    雨文_yuwencc1009閱讀 194評論 0 0
  • 女兒對我的工作充滿好奇,可能是我經常帶著女兒工作的原因,她對我的工作環(huán)境、工作內容、工作流程、工作節(jié)奏非常熟悉,培...
    宋阿娜閱讀 125評論 0 6

友情鏈接更多精彩內容