利用Dockerfile優(yōu)化Nestjs構(gòu)建鏡像大小詳情
前言
眾所周知,Node.js項(xiàng)目在部署的時(shí)候,無(wú)論是在虛擬機(jī)部署,還是使用docker
進(jìn)行部署,無(wú)非都是要先npm install
,然后把整個(gè)node_modules
丟上去,最后啟動(dòng)服務(wù)
但是有些開發(fā)依賴在生產(chǎn)環(huán)境部署的時(shí)候是不需要的。如果能每次打包只打包生產(chǎn)依賴,那就極大的減少node_modules
大小
所以當(dāng)時(shí)我在優(yōu)化公司的nestjs項(xiàng)目時(shí),苦苦尋找解決方案,就找到了這一篇文章,英文版原本在這里 www.tomray.dev/nestjs-dock…
原文開始
這是一篇手把手的教程,教你如何在制作nestjs
鏡像時(shí),能夠編寫出一個(gè)優(yōu)化生產(chǎn)依賴的Dockerfile
有了這個(gè)Dockerfile
,無(wú)論是在本地開發(fā)環(huán)境,還是在容器環(huán)境都能很輕松完成部署
P.S 如果你想直接復(fù)制最終的Dockerfile
,請(qǐng)直接跳到文章末尾
開始編寫Dockerfile
每個(gè)鏡像都可以視為一個(gè)單獨(dú)的軟件包,你可以通過(guò)編寫Dockerfile
告訴docker
如何來(lái)打包鏡像
讓我們開始編寫吧,首先,先創(chuàng)建一個(gè)空的文件
touch Dockerfile
然后把我們的指令添加到Dockerfile
里面,并且注釋每一步是干什么
# 基礎(chǔ)鏡像 FROM node:18 # 創(chuàng)建一個(gè)應(yīng)用目錄 WORKDIR /usr/src/app # 這個(gè)星號(hào)通配符意思是復(fù)制package.json和package-lock.json,復(fù)制到當(dāng)前應(yīng)用目錄 COPY package*.json ./ # 安裝應(yīng)用依賴 RUN npm install # 安裝完畢后復(fù)制當(dāng)前目錄所有文件到鏡像目錄里面 COPY . . # 執(zhí)行npm run build 后生成dist目錄 RUN npm run build # 使用打包后的鏡像 CMD ["node","dist/main.js"]
同樣的,創(chuàng)建.gitignore
文件,我們可以把那些不需要經(jīng)過(guò)docker
打包的文件給忽略掉
touch .dockerignore
把一下文件給排除忽略掉
Dockerfile .dockerignore node_modules npm-debug .log dist
在本地測(cè)試下
如果你在本地安裝了docker
,可以在本地進(jìn)行打包測(cè)試,讓我們來(lái)瞧瞧是否如預(yù)期中那樣打包鏡像
在命令行中執(zhí)行以下命令,當(dāng)然,你也可以把nest-app-demo
換成你想要的鏡像名,需要注意的是,不要忘記后面的.
號(hào)!
docker build -t nest-app-demo .
接著你可以在你本機(jī)執(zhí)行以下命令,查看是否已經(jīng)成功打包了鏡像
docker images
噢,感謝上帝,已經(jīng)成功打包成鏡像了,可以看到我們的命名nest-app-demo
就像只肥碩的土撥鼠靜靜的躺在鏡像列表里面
docker images REPOSITORY TAG IMAGE ID CREATED SIZE nest-app-demo latest 004f7f222139 31 seconds ago 1.24GB
緊接著讓我們來(lái)把鏡像給跑起來(lái),映射到本機(jī)80
端口,如果端口被占用可以使用其他端口
docker run -p 80:3000 nest-app-demo
這時(shí)候你就在瀏覽器中輸入http://localhost
進(jìn)行訪問(wèn),可以看到容器正常啟動(dòng)。 如果你想刪除那些正在運(yùn)行的容器,可以使用以下命令進(jìn)行刪除
docker rm -f $(docker ps -aq)
Dockerfile 生產(chǎn)環(huán)境優(yōu)化
好了,現(xiàn)在我們對(duì)鏡像包進(jìn)行壓縮了,因?yàn)榭梢钥吹剑壳扮R像大小是1.24G,噢,上帝,真是太大了!
讓我們來(lái)看看之前編寫的Dockerfile
,看如何對(duì)它進(jìn)行優(yōu)化
使用Alpine node鏡像
強(qiáng)烈推薦使用node:18-alpine
而不是node:18
,使用alpine
的鏡像可以直接把鏡像體積從1.24g減少到466MB!
添加 NODE_ENV 環(huán)境變量
很多依賴包會(huì)根據(jù)當(dāng)前的NODE_ENV
環(huán)境變量而進(jìn)行判斷是否優(yōu)化壓縮,所以我們可以在Dockerfile
里面把環(huán)境變量加進(jìn)去,設(shè)置為production
ENV NODE_ENV production
順便提一句,如果你不知道如何在Nestjs里面通過(guò)配置文件進(jìn)行環(huán)境變量設(shè)置的話,可以看下這篇入門文章www.tomray.dev/nestjs-conf…
使用npm ci 而不是npm install
npm 比較推薦使用npm ci
而不是npm install
來(lái)打包鏡像,至于原因可以點(diǎn)擊這里查看docs.npmjs.com/cli/v8/comm…
"
npm ci
與npm install
很相似,除了當(dāng)它用于自動(dòng)化時(shí),如測(cè)試平臺(tái),持續(xù)集成和部署————或者任何你想確保能有一個(gè)干凈的依賴安裝環(huán)境"
正好符合我們現(xiàn)在的情況,所以我們要使用npm ci
來(lái)替換npm install
RUN npm ci
使用User指令
默認(rèn)情況下,Dockerfile
會(huì)使用root
權(quán)限來(lái)構(gòu)建你的鏡像,這會(huì)存在一定的安全風(fēng)險(xiǎn),在這里,我們已經(jīng)擁有一個(gè)叫node
的用戶,我們可以直接使用它
USER node
當(dāng)你在使用COPY
指令時(shí),添加標(biāo)志以確保用戶能夠擁有正確的權(quán)限也是一種好做法,比如可以使用--chown=node:node
COPY --chown=node:node package*.json ./
使用多階段構(gòu)建
在Dockerfile
中,你可以定義多階段構(gòu)建,這是一種通過(guò)多個(gè)鏡像構(gòu)建出最優(yōu)鏡像的方式,可以使得最后生成的鏡像最小化
################### # BUILD FOR LOCAL DEVELOPMENT ################### FROM node:18-alpine As development # ...開發(fā)環(huán)境構(gòu)建說(shuō)明 ################### # BUILD FOR PRODUCTION ################### # 生產(chǎn)環(huán)境基礎(chǔ)鏡像 FROM node:18-alpine As build # ... 這里是構(gòu)建說(shuō)明 ################### # PRODUCTION ################### # 生產(chǎn)環(huán)境基礎(chǔ)鏡像 FROM node:18-alpine As production # ... 你的生產(chǎn)環(huán)境構(gòu)建說(shuō)明
上面是多階段構(gòu)建的3個(gè)階段:
development
這是用于本地環(huán)境構(gòu)建鏡像時(shí)的階段build
這是用于構(gòu)建生產(chǎn)鏡像的階段production
復(fù)制構(gòu)建完畢后的文件并且啟動(dòng)服務(wù)
如果你不需要在本地環(huán)境使用docker
啟動(dòng)你的Nestjs應(yīng)用,可以把前兩個(gè)階段合二為一
上述多階段設(shè)置的好處在于,這樣你就有了一個(gè)可以在本地開發(fā)中使用的Dockerfile
(與docker-compose
組合在一起)。同時(shí)創(chuàng)建一個(gè)用于生產(chǎn)的優(yōu)化Docker
鏡像。
如果你對(duì)使用Docker Compose
的多階段Dockerfile
進(jìn)行本地開發(fā)(熱加載)有興趣,可以點(diǎn)擊看這篇文章www.tomray.dev/nestjs-dock…
最終的Dockerfile
通過(guò)上述使用的方案進(jìn)行優(yōu)化后,最終的Dockerfile
如下,他可以幫助我們構(gòu)建出最優(yōu)的鏡像
################### # BUILD FOR LOCAL DEVELOPMENT ################### FROM node:18-alpine As development # 創(chuàng)建應(yīng)用目錄 WORKDIR /usr/src/app # 復(fù)制依賴清單到容器鏡像里. # 這個(gè)星號(hào)通配符意思是復(fù)制package.json和package-lock.json,復(fù)制到當(dāng)前應(yīng)用目錄. # 首先復(fù)制這個(gè)選項(xiàng)可以防止在每次代碼更改時(shí)重新運(yùn)行npm install. COPY --chown=node:node package*.json ./ # 使用npm ci來(lái)安裝依賴而不是npm install RUN npm ci # 復(fù)制安裝后的依賴包到當(dāng)前目錄下 COPY --chown=node:node . . # 使用指定的用戶而不是root權(quán)限用戶 USER node ################### # BUILD FOR PRODUCTION ################### FROM node:18-alpine As build WORKDIR /usr/src/app COPY --chown=node:node package*.json ./ # 我們需要通過(guò)Nest CLI 來(lái)執(zhí)行npm run build,這是個(gè)開發(fā)依賴,然后把安裝后依賴全部復(fù)制到指定目錄 COPY --chown=node:node --from=development /usr/src/app/node_modules ./node_modules COPY --chown=node:node . . # 執(zhí)行打包命令 RUN npm run build # 設(shè)置生產(chǎn)環(huán)境變量 ENV NODE_ENV production # 運(yùn)行' npm ci '會(huì)刪除現(xiàn)有的node_modules目錄,并傳入——only=production確保只安裝了生產(chǎn)依賴項(xiàng)。這確保node_modules目錄盡可能優(yōu)化 RUN npm ci --only=production && npm cache clean --force USER node ################### # PRODUCTION ################### FROM node:18-alpine As production # 將生產(chǎn)依賴和打包后的文件復(fù)制到指定目錄下 COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules COPY --chown=node:node --from=build /usr/src/app/dist ./dist # 啟動(dòng)服務(wù) CMD [ "node", "dist/main.js" ]
可以看到,最后打包的鏡像只有189MB大小
REPOSITORY TAG IMAGE ID CREATED SIZE nest-cloud-run latest 004f7f222139 31 seconds ago 189MB
到此這篇關(guān)于利用Dockerfile優(yōu)化Nestjs構(gòu)建鏡像大小詳情的文章就介紹到這了,更多相關(guān)Dockerfile優(yōu)化Nestjs內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker搭建本地私有倉(cāng)庫(kù)的詳細(xì)步驟
本篇文章主要介紹了Docker搭建本地私有倉(cāng)庫(kù)的詳細(xì)步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02docker?環(huán)境搭建、docker?與容器常用指令大全(推薦)
這篇文章主要介紹了docker?環(huán)境搭建、docker?與容器常用指令大全,主要包括docker容器操作命令匯總,文中介紹需要注意的是如果想要?jiǎng)h除一個(gè)容器,需要先停止該容器且如果鏡像中有運(yùn)行狀態(tài)的容器,也是無(wú)法刪除容器的,需要的朋友可以參考下2022-06-06Docker安裝阿里云服務(wù)器和在虛擬機(jī)安裝遇到的坑(問(wèn)題小結(jié))
這篇文章主要介紹了Docker安裝阿里云服務(wù)器和在虛擬機(jī)安裝遇到的坑,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03Docker搭建Harbor公開倉(cāng)庫(kù)的方法示例
這篇文章主要介紹了Docker搭建Harbor公開倉(cāng)庫(kù)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06簡(jiǎn)簡(jiǎn)單單使用Docker部署Confluence
本文使用的環(huán)境是docker17版本,重點(diǎn)給大家講解使用Docker部署Confluence的問(wèn)題,本文給大家介紹的很好對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-06-06docker離線部署docker,部署業(yè)務(wù)方式
這篇文章主要介紹了docker離線部署docker,部署業(yè)務(wù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01docker-compose快速搭建docker私有倉(cāng)庫(kù)的步驟
這篇文章主要介紹了docker-compose快速搭建docker私有倉(cāng)庫(kù)的步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12