docker構(gòu)建并啟動前端完整流程
docker文件示例代碼:
# Use a minimal image for development FROM node:18-alpine # Set working directory inside the container WORKDIR /app # Copy package.json and package-lock.json (or yarn.lock) into the container COPY package.json package-lock.json* ./ # Install the app dependencies with --legacy-peer-deps to bypass the peer dependency conflict RUN npm install --legacy-peer-deps # Copy the rest of the application files into the container COPY . . # Expose the port the app will run on EXPOSE 3000 # Start the Next.js app in development mode CMD ["npm", "run", "dev"]
這段 Dockerfile 用于構(gòu)建一個基于 Node.js 18 Alpine 版本的容器,并運行一個 Next.js 應(yīng)用。
逐行解析
1. 選擇基礎(chǔ)鏡像
FROM node:18-alpine
- 使用
node:18-alpine作為基礎(chǔ)鏡像,alpine是 輕量級 Linux 版本,比node:18體積更小,減少 Docker 鏡像的大小。
2. 設(shè)置工作目錄
WORKDIR /app
- 在 容器內(nèi) 創(chuàng)建
/app目錄,并把它作為 當前工作目錄。 - 之后的所有操作都會在
/app目錄下執(zhí)行。
3. 復(fù)制package.json和package-lock.json
COPY package.json package-lock.json* ./
- 只復(fù)制
package.json和package-lock.json,避免不必要的文件影響npm install緩存。 package-lock.json*這樣寫是為了:- 兼容
package-lock.json和package-lock.json.gz(如果存在)。
- 兼容
4. 安裝依賴
RUN npm install --legacy-peer-deps
npm install安裝 Node.js 依賴。--legacy-peer-deps選項用于:- 跳過 peerDependencies(依賴版本沖突時不報錯)。
- 適用于 舊項目或有沖突的依賴。
5. 復(fù)制項目代碼
COPY . .
- 復(fù)制 本地所有文件 到 容器的
/app/目錄。 - 這里 不會重復(fù)安裝依賴,因為
npm install早就運行過了。
6. 開放端口
EXPOSE 3000
- 這個 只是聲明 容器會使用
3000端口,但默認不會讓外部訪問。 - 真正讓外部訪問時,需要
-p參數(shù):這樣才能 映射端口,讓瀏覽器訪問docker run -p 3000:3000 my-next-app
http://localhost:3000。
7. 運行 Next.js 應(yīng)用
CMD ["npm", "run", "dev"]
- 容器啟動時執(zhí)行 npm run dev,即 開發(fā)模式運行 Next.js。
- 這個命令等價于:
npm run dev
dev腳本通常在package.json里:"scripts": { "dev": "next dev" }- Next.js 開發(fā)服務(wù)器會在 localhost:3000 運行。
完整流程
- 基于 node:18-alpine 創(chuàng)建一個容器
- 在 /app 目錄下工作
- 復(fù)制 package.json 并安裝依賴
- 復(fù)制整個項目代碼
- 暴露 3000 端口
- 運行 npm run dev 啟動 Next.js 服務(wù)器
如何使用
1. 構(gòu)建鏡像
docker build -t my-next-app .
2. 運行容器
docker run -p 3000:3000 my-next-app
然后在瀏覽器訪問:
http://localhost:3000
如果一切正常,你會看到 Next.js 應(yīng)用的頁面!??
設(shè)置工作目錄,所有操作都會在 /app 目錄下執(zhí)行。
當前app目錄下沒有內(nèi)容吧,那怎么復(fù)制 package.json 和 package-lock.json
在 WORKDIR /app 之后,/app 目錄雖然存在,但還是空的。
但是,Docker COPY 命令不會受這個影響,它會從宿主機(你的電腦)復(fù)制文件到 /app 目錄下。
詳細流程
WORKDIR /app COPY package.json package-lock.json* ./
?? 第一步:WORKDIR /app
- 這會 切換到 /app 目錄,如果
/app目錄不存在,Docker 會自動創(chuàng)建它。
?? 第二步:COPY package.json package-lock.json* ./
COPY命令會從 宿主機(你的電腦) 的 當前目錄 復(fù)制package.json和package-lock.json到/app目錄下。./代表目標路徑是 當前目錄,因為WORKDIR /app已經(jīng)切換到/app,所以./實際上就是/app/。
舉個例子
假設(shè)你的 項目目錄 結(jié)構(gòu)如下:
/my-project ├── Dockerfile ├── package.json ├── package-lock.json ├── src/ ├── pages/ └── node_modules/
你在 /my-project 目錄下運行:
docker build -t my-next-app .
Docker 執(zhí)行過程:
1?? WORKDIR /app → 在容器內(nèi)創(chuàng)建并切換到 /app
2?? COPY package.json package-lock.json* ./ → 把 package.json 和 package-lock.json 復(fù)制到 /app/
3?? RUN npm install --legacy-peer-deps → 在 /app/ 里安裝依賴
4?? COPY . . → 復(fù)制 所有剩余文件(比如 src/、pages/)
總結(jié)
WORKDIR /app只是 切換工作目錄,不影響后續(xù)COPYCOPY package.json package-lock.json* ./復(fù)制package.json和package-lock.json到/app/COPY . .復(fù)制所有剩余文件- 這樣可以 優(yōu)化緩存,加快構(gòu)建速度 ??
如果還是不懂,那就先理解下面的內(nèi)容。。
COPY package.json package-lock.json ./這行代碼的意思
COPY package.json package-lock.json* ./
它的作用是:
?? 從宿主機(你的電腦)復(fù)制 package.json 和 package-lock.json 到 Docker 容器的 /app/ 目錄下。
拆解解釋
COPY package.json package-lock.json* ./
package.json package-lock.json*→ 要復(fù)制的文件(來自你的 本地電腦)./→ 目標路徑(容器內(nèi)的 /app/)
為什么./代表/app/?
因為 之前已經(jīng)有 WORKDIR /app 了:
WORKDIR /app COPY package.json package-lock.json* ./
WORKDIR /app讓 當前工作目錄 變成/appCOPY package.json package-lock.json* ./里的./指的是 當前工作目錄- 所以 ./ 實際上等同于 /app/
相當于:
COPY package.json package-lock.json* /app/
舉個例子
假設(shè)你的 宿主機(電腦)的項目目錄:
/my-project ├── Dockerfile ├── package.json ├── package-lock.json ├── src/ ├── pages/ └── node_modules/
當你運行:
docker build -t my-next-app .
Docker 會執(zhí)行:
1?? WORKDIR /app → 現(xiàn)在 /app 是容器內(nèi)的工作目錄
2?? COPY package.json package-lock.json* ./ → 復(fù)制 package.json 和 package-lock.json 到 /app/ 目錄
3?? RUN npm install --legacy-peer-deps → 在 /app/ 里安裝依賴
4?? COPY . . → 復(fù)制 剩下的所有文件(比如 src/、pages/)
總結(jié)
? ./ 代表 容器里的 /app/,因為 WORKDIR /app 讓 /app 成為了當前目錄
? COPY package.json package-lock.json* ./ 相當于 COPY package.json package-lock.json* /app/
? 先復(fù)制依賴文件再復(fù)制整個項目,是為了優(yōu)化 Docker 緩存,加快構(gòu)建速度 ??
COPY . .是什么意思,為什么這里是兩個..
COPY . .
這條指令的作用是:
?? 把宿主機(你的電腦)的 當前目錄(.)的 所有文件 復(fù)制到 容器內(nèi)的當前目錄(.)。
由于 WORKDIR /app 設(shè)定了工作目錄為 /app,所以 . 實際上是 /app/,最終效果是:
?? 把宿主機的整個項目目錄復(fù)制到容器的 /app/ 目錄里。
拆解解釋
COPY <源路徑> <目標路徑>
- 第一個
.(源路徑):指的是 宿主機上的當前目錄(Docker 構(gòu)建時的Dockerfile所在目錄) - 第二個
.(目標路徑):指的是 容器內(nèi)的當前工作目錄(WORKDIR /app已經(jīng)設(shè)置)
所以:
WORKDIR /app COPY . .
等價于:
COPY . /app/
舉個例子
假設(shè)你的 本地項目目錄(宿主機):
/my-project ├── Dockerfile ├── package.json ├── package-lock.json ├── src/ ├── pages/ ├── node_modules/ ├── public/ └── .gitignore
你運行:
docker build -t my-next-app .
Docker 執(zhí)行過程:
1?? WORKDIR /app → 切換到 /app/ 目錄(如果沒有,就創(chuàng)建它)
2?? COPY package.json package-lock.json* ./ → 復(fù)制 package.json 和 package-lock.json 到 /app/
3?? RUN npm install --legacy-peer-deps → 安裝依賴
4?? COPY . . → 復(fù)制整個項目到 /app/,包括 src/、pages/、public/ 等
最終容器內(nèi)的 /app/ 目錄會變成:
/app ├── package.json ├── package-lock.json ├── src/ ├── pages/ ├── node_modules/ (npm install 之后才有) ├── public/ ├── .gitignore
這樣容器就擁有了完整的項目代碼,可以運行 Next.js 了!??
為什么要COPY . .?
? 把整個項目復(fù)制到容器內(nèi),保證 npm run dev 可以運行
? 必須在 npm install 之后執(zhí)行,避免 node_modules/ 被覆蓋
? 確保 src/、pages/ 這些代碼文件都能進入容器
總結(jié)
COPY . .就是 COPY . /app/- 把宿主機(本機)的項目文件,復(fù)制到容器內(nèi)的
/app/目錄 - 必須在
npm install之后執(zhí)行,避免影響node_modules/ - 這樣容器就可以運行 Next.js 應(yīng)用了 ??
COPY .. → 復(fù)制整個項目到 /app/,包括 src/、pages/、public/ 等,這樣不就會重復(fù)復(fù)制前面已經(jīng)復(fù)制過的文件了么,比如package.json package-lock.json
是的,COPY . . 確實會再次復(fù)制 package.json 和 package-lock.json,但這不會影響構(gòu)建結(jié)果,主要目的是 優(yōu)化 Docker 構(gòu)建緩存,加快構(gòu)建速度。
為什么先COPY package.json package-lock.json ./再COPY . .?
先單獨復(fù)制package.json和package-lock.json
COPY package.json package-lock.json* ./ RUN npm install --legacy-peer-deps
這樣做的好處:
- Docker 會緩存
npm install結(jié)果,下次構(gòu)建時,如果package.json沒有改動,就不會重新安裝依賴,直接用緩存的node_modules! - 避免
npm install被COPY . .之后的代碼改動影響(如果src/里的文件改了,不影響node_modules)。
再復(fù)制整個項目
COPY . .
這樣做的好處:
- 確保 所有代碼文件(
src/、pages/、public/)都能進入容器。 - 不影響
node_modules/緩存,因為npm install之前已經(jīng)執(zhí)行過了。
如果不先COPY package.json,直接COPY . .會怎樣?
如果你只寫:
COPY . . RUN npm install --legacy-peer-deps
問題在于:
- 每次項目代碼有一點改動(比如
src/文件變了),COPY . .都會讓 Docker 重新執(zhí)行RUN npm install,導(dǎo)致浪費時間! npm install需要很久,每次構(gòu)建都會重新下載依賴,非常慢。
總結(jié)
? 先 COPY package.json package-lock.json ./,讓 npm install 結(jié)果被緩存,加快構(gòu)建
? 再 COPY . .,確保所有代碼文件(src/、pages/ 等)被復(fù)制
? 即使 package.json 被重復(fù)復(fù)制,也不會影響最終構(gòu)建速度 ??
為什么先COPY package.json package-lock.json ./,可以讓 npm install 結(jié)果被緩存
Docker 構(gòu)建時,會緩存每一層命令的結(jié)果,如果前面某一層的輸入沒有變,Docker 就不會重新執(zhí)行它,而是直接用緩存。
Docker 的緩存機制
當你運行 docker build 時,Docker 會:
- 逐行讀取 Dockerfile
- 檢查每一層是否有變動
- 如果某一層和上次構(gòu)建時相同,就復(fù)用緩存
- 如果某一層變了,后面的所有層都會重新執(zhí)行(緩存失效)
舉個例子
沒有單獨復(fù)制package.json,直接COPY . .
# 設(shè)置工作目錄 WORKDIR /app # 直接復(fù)制整個項目 COPY . . # 安裝依賴 RUN npm install --legacy-peer-deps
這里的問題
COPY . .會把 所有文件(包括src/、pages/、public/)都復(fù)制到/app/- 如果
src/里的代碼有改動,整個COPY . .就會變動 - Docker 發(fā)現(xiàn)
COPY . .變了,就會讓npm install重新執(zhí)行,緩存失效 npm install需要很長時間,每次構(gòu)建都要重復(fù)下載依賴,太慢了!??
優(yōu)化方法:先COPY package.json package-lock.json ./
# 設(shè)置工作目錄 WORKDIR /app # 先復(fù)制 package.json 和 package-lock.json COPY package.json package-lock.json* ./ # 運行 npm install,并緩存 node_modules RUN npm install --legacy-peer-deps # 復(fù)制剩下的所有文件 COPY . .
為什么這樣能加速構(gòu)建?
1?? Docker 先執(zhí)行 COPY package.json package-lock.json ./
- 只復(fù)制
package.json和package-lock.json,不會受src/文件改動影響
2?? 然后執(zhí)行 RUN npm install --legacy-peer-deps
- 如果
package.json沒變,Docker 直接復(fù)用上次構(gòu)建的node_modules - 跳過
npm install,節(jié)省時間!??
3?? 最后執(zhí)行 COPY . .
- 復(fù)制
src/、pages/、public/等代碼文件 - 即使代碼變了,
npm install也不會重新執(zhí)行
這樣做的結(jié)果
? 如果 package.json 沒變,Docker 直接復(fù)用 node_modules,構(gòu)建速度快很多
? 即使 src/ 代碼變了,也不會觸發(fā) npm install,不會浪費時間
? 整個構(gòu)建流程更高效,省時省力 ??
時間對比
| 方法 | 構(gòu)建時間(假設(shè) npm install 需要 2 分鐘) |
|---|---|
直接 COPY . . | 每次構(gòu)建都要等 2 分鐘(因為 npm install 總是重新運行) |
先 COPY package.json,再 COPY . . | 如果 package.json 沒變,構(gòu)建只需要幾秒! |
?? 這樣優(yōu)化后,構(gòu)建速度可以快 10 倍以上! ??
如果 Docker 關(guān)閉后重新啟動,還需要重新安裝依賴嗎?
? 如果你只是重啟 Docker(比如 docker stop → docker start),不需要重新安裝依賴,因為容器的文件系統(tǒng)還在,node_modules/ 也還在。
? 但是,如果你刪除了容器或構(gòu)建了新鏡像,就需要重新安裝依賴!
分情況討論
1. 只是重啟 Docker
docker stop my-container # 關(guān)閉容器 docker start my-container # 重新啟動
- node_modules/ 還在,不需要重新安裝依賴
- 應(yīng)用可以直接運行
- 適用于日常使用
2. 刪除容器后再啟動
docker rm my-container # 刪除容器 docker run my-image # 重新運行
- 容器被刪除,所有文件(包括
node_modules/)都會丟失 - 需要重新
npm install - 這時 Docker 會根據(jù)
Dockerfile重新安裝依賴
3. 重新docker build
docker build -t my-app . # 重新構(gòu)建鏡像 docker run my-app # 運行新容器
- 如果
package.json沒變,Docker 可能會復(fù)用npm install的緩存 - 如果
package.json變了,npm install會重新運行 - 推薦使用 Docker Volume 來持久化
node_modules/(見下面的方法)
如何讓node_modules/不丟失?(Docker Volume 持久化)
方法 1??:使用docker-compose綁定node_modules目錄
創(chuàng)建 docker-compose.yml:
version: '3'
services:
app:
build: .
volumes:
- .:/app
- /app/node_modules
ports:
- "3000:3000"
這樣即使你刪除容器,node_modules/ 也不會丟失。
方法 2??:手動掛載 Volume
運行容器時,使用 -v 選項:
docker run -v my-node-modules:/app/node_modules -p 3000:3000 my-app
- 這樣
node_modules/會存儲在 Docker Volume 里 - 即使你刪除容器,依賴也不會丟失
總結(jié)
| 情況 | 是否需要重新安裝依賴? |
|---|---|
僅重啟 Docker (docker stop → docker start) | ? 不需要,node_modules/ 還在 |
刪除容器后重新運行 (docker rm + docker run) | ? 需要,文件丟失 |
重新構(gòu)建鏡像 (docker build) | ?? 可能需要,取決于 Docker 緩存 |
使用 Volume (-v 綁定 node_modules/) | ? 不需要,node_modules/ 保留在 Volume |
? 推薦使用 Volume,這樣即使容器被刪,依賴也不會丟失 ??
如果你關(guān)了電腦、退出了 Docker,下次啟動后還需要重新安裝依賴嗎?
? 大多數(shù)情況下,不需要重新安裝依賴!
如果你只是 關(guān)機、退出 Docker,再次啟動,你的 容器和 node_modules/ 依然會保留,不需要重新 npm install。
但 如果你刪除了容器、清理了 Docker 數(shù)據(jù),或者用了 --rm 運行容器,就需要重新安裝依賴!
具體情況分析
| 操作 | 需要重新安裝依賴嗎? | 原因 |
|---|---|---|
| 關(guān)機后重新開機 | ? 不需要 | Docker 會保留容器和 node_modules/ |
| 退出 Docker 后重新啟動 | ? 不需要 | 只要容器沒有被刪除,node_modules/ 還在 |
用 docker stop 停止容器,再 docker start | ? 不需要 | node_modules/ 還在,直接啟動即可 |
用 docker rm 刪除容器 | ? 需要 | node_modules/ 被刪,需要重新安裝 |
用 docker build 重新構(gòu)建鏡像 | ?? 可能需要 | 如果 package.json 沒變,可能會用緩存 |
用 docker run --rm 運行臨時容器 | ? 需要 | --rm 讓容器退出時自動刪除,node_modules/ 會丟失 |
如何確保關(guān)機后node_modules/不丟失?
方法 1:使用持久化 Volume
docker run -v my-node-modules:/app/node_modules -p 3000:3000 my-app
這樣 node_modules/ 會存儲在 Docker Volume 里,即使容器被刪除,依賴也不會丟失。
方法 2:用docker-compose管理項目
創(chuàng)建 docker-compose.yml:
version: '3'
services:
app:
build: .
volumes:
- .:/app
- /app/node_modules
ports:
- "3000:3000"
然后啟動:
docker-compose up -d
這樣即使你重啟 Docker 或關(guān)機,node_modules/ 依然會保留。
總結(jié)
如果你只是關(guān)機、退出 Docker, 依賴不會丟失,開機后可以直接運行容器 ??
但如果刪除了容器,就需要重新安裝 npm install!
到此這篇關(guān)于docker構(gòu)建并啟動前端的文章就介紹到這了,更多相關(guān)docker構(gòu)建啟動前端內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
docker 學(xué)習(xí)筆記之docker連接網(wǎng)絡(luò)的設(shè)置
本篇文章主要介紹了docker 學(xué)習(xí)筆記之docker連接網(wǎng)絡(luò)的設(shè)置 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02
Docker 和 Containerd 目錄結(jié)構(gòu)及存儲機制詳解
Docker和Containerd是兩種流行的容器運行時工具,它們都有自己的目錄結(jié)構(gòu)和存儲機制,本文詳細介紹了Docker和Containerd的目錄結(jié)構(gòu)和存儲機制,并對比了它們之間的主要區(qū)別,包括存儲路徑、掛載點管理、配置文件和日志文件,感興趣的朋友一起看看吧2025-02-02
Docker網(wǎng)絡(luò)IP地址沖突的解決方法
本文主要介紹了Docker網(wǎng)絡(luò)IP地址沖突的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
dockerfile部署前端vue打包的ist文件實戰(zhàn)
這篇文章主要為大家介紹了dockerfile部署前端vue打包的ist文件實戰(zhàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10
谷歌技術(shù)人員解決Docker鏡像體積太大問題的方法
這篇文章主要介紹了谷歌技術(shù)人員解決Docker鏡像體積太大問題的方法,涉及虛擬機,谷歌docker鏡像構(gòu)建實踐及構(gòu)建工具bazel的介紹等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。2017-11-11
使用Docker部署openGauss國產(chǎn)數(shù)據(jù)庫的操作方法
openGauss是一款支持SQL2003標準語法,支持主備部署的高可用關(guān)系型數(shù)據(jù)庫,這篇文章主要介紹了使用Docker部署openGauss國產(chǎn)數(shù)據(jù)庫,需要的朋友可以參考下2022-10-10
Docker的安裝方法及運行Docker Swarm模式的使用
本文給大家簡單介紹docker的安裝以及1.12版本的swarm模式的使用,包括docker的安裝和配置,對docker swarm簡單使用感興趣的朋友一起看看吧2016-11-11

