Docker Next.js 本地部署技能 是做什麼的?
目的
使用此技能來透過具版本標籤的映像檔,建置並執行 Next.js 應用程式。
此技能不得硬式編碼專案名稱。除非使用者提供特定名稱,否則應從目前儲存庫推斷映像名稱。
專案名稱解析
在建置前,請決定這些值:
PROJECT_NAME=<解析後的專案名稱>
IMAGE_NAME=<解析後的映像名稱>
IMAGE_VERSION=<解析後的版本>
IMAGE_TAG=${IMAGE_NAME}:${IMAGE_VERSION}
CONTAINER_NAME=<解析後的容器名稱>
ENV_FILE=<解析後的環境變數檔案>
HOST_PORT=<解析後的主機通訊埠>
CONTAINER_PORT=<解析後的容器通訊埠>
解析規則:
-
如果使用者提供映像名稱,則使用該名稱。
-
否則,讀取
package.json並使用name欄位。 -
如果
package.json沒有name,則使用目前資料夾名稱。 -
正規化映像名稱:
- 全部小寫
- 將空格和底線替換為連字號
- 移除無效的 Docker 映像名稱字元
-
如果使用者提供版本,則使用該版本。
-
否則,預設為
1.0.0。 -
如果使用者提供容器名稱,則使用該名稱。
-
否則,使用正規化後的映像名稱作為容器名稱。
-
如果使用者提供環境變數檔案,則使用該檔案。
-
否則,預設為
.env.production。 -
如果使用者提供通訊埠,則使用該通訊埠。
-
否則,預設為
HOST_PORT=4000和CONTAINER_PORT=3000。
範例:
package.json name: nextjs-skill-app-workshop
PROJECT_NAME=nextjs-skill-app-workshop
IMAGE_NAME=nextjs-skill-app-workshop
IMAGE_VERSION=1.0.0
IMAGE_TAG=nextjs-skill-app-workshop:1.0.0
CONTAINER_NAME=nextjs-skill-app-workshop
ENV_FILE=.env.production
HOST_PORT=4000
CONTAINER_PORT=3000
安全規則
在執行任何建置或執行指令前:
-
確認目前工作目錄是專案根目錄。
-
確認
Dockerfile存在。 -
確認環境變數檔案存在。
-
確認 Docker 已安裝且正在執行。
-
檢查請求的映像標籤是否已存在於本地端。
-
檢查請求的容器名稱是否已存在。
-
切勿從環境變數檔案中列印機密資訊。
-
除非使用者明確要求,否則不要使用
latest標籤。 -
不要執行破壞性的清理指令,例如:
docker system prunedocker image prunedocker volume prune
-
未經使用者明確確認,請勿停止、移除或取代現有容器。
-
除非使用者清楚確認,否則不要重新建置現有的版本標籤。
預先檢查
首先執行這些檢查:
pwd
ls -la
測試 -f package.json && echo "OK: package.json 已找到" || echo "WARN: package.json 未找到"
測試 -f Dockerfile && echo "OK: Dockerfile 已找到" || echo "ERROR: Dockerfile 未找到"
測試 -f "$ENV_FILE" && echo "OK: 環境變數檔案已找到: $ENV_FILE" || echo "ERROR: 環境變數檔案未找到: $ENV_FILE"
docker --version
docker info >/dev/null && echo "OK: Docker 守護程序正在執行" || echo "ERROR: Docker 守護程序未在執行"
如果缺少 Dockerfile,則停止並報告問題。
如果缺少環境變數檔案,則停止並報告問題。除非使用者要求,否則不要建立佔位環境變數檔案。
如果 Docker 守護程序未在執行,則停止並告知使用者啟動 Docker Desktop 或 Docker Engine。
建議的輔助指令
從 package.json 推斷映像名稱:
node -p "require('./package.json').name"
如果 package.json 不存在或沒有 name,則使用目前目錄名稱:
basename "$PWD"
若要手動正規化專案名稱,請使用小寫連字號格式 (kebab-case)。
範例:
我的 Next 應用程式 -> my-next-app
nextjs_skill_app -> nextjs-skill-app
版本標籤檢查
在建置前,檢查請求的映像標籤是否已存在:
docker image inspect "$IMAGE_TAG" >/dev/null 2>&1 \
&& echo "EXISTS: $IMAGE_TAG" \
|| echo "AVAILABLE: $IMAGE_TAG"
同時列出此映像的現有本地版本:
docker images "$IMAGE_NAME" --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}"
如果請求的映像標籤已存在:
- 不要執行
docker build。 - 報告該版本已存在於本地端。
- 建議下一個修補版本,例如
1.0.1。 - 詢問使用者是要使用新版本,還是明確重新建置相同標籤。
僅在使用者清楚確認時才重新建置現有標籤。
容器名稱檢查
在執行容器前,檢查容器名稱是否已存在:
docker ps -a --filter "name=^/${CONTAINER_NAME}$" \
--format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
如果同名的容器已存在:
- 不要使用相同名稱執行另一個容器。
- 報告現有容器的狀態。
- 詢問使用者是要停止/移除它,還是使用不同的容器名稱。
- 不要自動移除它。
建置指令
如果映像標籤不存在,請執行:
docker build -t "$IMAGE_TAG" .
建置後,驗證映像是否存在:
docker image inspect "$IMAGE_TAG" >/dev/null \
&& echo "OK: 映像建置成功: $IMAGE_TAG" \
|| echo "ERROR: 建置後未找到映像: $IMAGE_TAG"
執行指令
如果映像存在且容器名稱可用,請執行:
docker run --restart=always -d \
--name "$CONTAINER_NAME" \
--env-file "$ENV_FILE" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
"$IMAGE_TAG"
執行後驗證
執行容器後,使用以下方式驗證:
docker ps --filter "name=^/${CONTAINER_NAME}$" \
--format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
docker logs --tail=80 "$CONTAINER_NAME"
curl -I "http://localhost:${HOST_PORT}"
預期結果:
- 容器狀態應為
Up。 - 通訊埠對應應包含
${HOST_PORT}->${CONTAINER_PORT}。 - 日誌不應顯示嚴重錯誤。
curl -I應回傳 HTTP 狀態碼,例如200、301、302、307或308。
如果 curl 失敗,請檢查日誌並回報可能的原因。
常見失敗處理
映像標籤已存在
回報:
映像標籤已存在於本地端:
<IMAGE_TAG>
建議操作:
- 使用新的修補版本,例如 1.0.1
- 或明確確認重新建置相同標籤
容器名稱已存在
回報:
容器已存在:
<CONTAINER_NAME>
請確認是否要停止/移除它,或提供不同的容器名稱。
通訊埠已被佔用
檢查:
lsof -i :"$HOST_PORT"
回報佔用該通訊埠的處理程序,並詢問使用者是否要變更 HOST_PORT。
環境變數檔案遺失
回報:
找不到環境變數檔案:
<ENV_FILE>
在該檔案存在之前,我無法使用 --env-file 執行容器。
請勿列印或推斷機密資訊。
Docker 守護程序未執行
回報:
Docker 已安裝,但守護程序未在執行。
請啟動 Docker Desktop 或 Docker Engine,然後重新執行預先檢查。
最終回覆格式
完成時,回報:
結果:
- 專案:<PROJECT_NAME>
- 映像:<IMAGE_TAG>
- 容器:<CONTAINER_NAME>
- 環境變數檔案:<ENV_FILE>
- 通訊埠:http://localhost:<HOST_PORT>
- 重新啟動策略:always
- 驗證:通過/失敗
使用的指令:
<列出重要指令>
備註:
<任何警告、現有映像/容器衝突或後續操作>
如果工作流程因現有版本標籤、缺少環境變數檔案、現有容器、Docker 錯誤或通訊埠衝突而停止,請清楚說明阻礙的問題以及最安全的下一步指令。