Docker 掛載後 node_modules 不見?bind mount 會遮住 image 裡的檔案
docker build 已完成 npm ci,啟動 Compose 卻說找不到套件。若設定有 .:/app,先檢查這個掛載:主機專案目錄會遮住容器原本的 /app,包含 image 建置時放進去的 /app/node_modules。 重新 build 同一份 image,不能讓被遮住的檔案穿過掛載顯示。
Docker bind mount 文件明確說明這個行為。原資料是被遮住,不代表 build 沒安裝或檔案已被刪除。以下為文件檢閱後的診斷指南;本次本機 daemon 無法連線,沒有執行容器命令。
先分清 image 內容與啟動後看到的內容
假設 Dockerfile 在 /app 安裝依賴,而 Compose 有以下開發用設定:
services: web: build: . working_dir: /app volumes: - .:/app主機沒有 node_modules 時,掛載後 /app 也不會憑空露出 image 的那份。主機有該目錄時,容器看到的則可能是主機安裝結果;其中原生模組與執行環境是否相容,需要另外確認。
可以把排查分成兩個問題:建置產物裡有沒有依賴?執行時到底掛了什麼?若連 build 的 COPY 都失敗,應先看 Docker build context 與 .dockerignore,還沒到本篇的掛載階段。
只列出 Mounts,找到遮住依賴的那一層
以下命令適用於已啟動、服務名為 web 的 Compose 專案。在該專案目錄執行;服務名不同需替換,命令在本文未實際執行:
docker compose ps -q web將輸出的單一容器 ID 填入下一行。範例 ID 是佔位字串,不要直接照貼:
docker inspect --format '{{json .Mounts}}' CONTAINER_ID這比輸出整份 inspect 更聚焦,也避免順帶列出容器環境變數。觀察每個 mount 的 Type、Source、Destination,尤其是 /app 與更深的 /app/node_modules。來源路徑也可能包含帳號或專案資訊,分享前先遮蔽。
接著核對該容器實際使用的 image ID,再用不掛專案目錄的臨時容器查看 image。以下只適用於 image 提供 /bin/sh、ls,且依賴目錄確實是 /app/node_modules 的情境;distroless image 或不同套件布局需另換檢查方式:
docker inspect --format '{{.Image}}' CONTAINER_IDdocker run --rm --entrypoint /bin/sh IMAGE_ID -c 'ls -ld /app/node_modules'若無掛載的 image 有目錄,原容器卻被 /app 的 bind mount 遮住,才有證據把下一步放在掛載設定。若 image 本身就沒有依賴,回頭查 build stage、安裝結果與工作目錄。Image 若宣告了其他 VOLUME,也要一併核對,不能只憑這行命令就認定所有路徑都沒有 mount。
選擇修法時,先決定誰管理依賴
只需要更新原始碼的專案,可縮小 bind mount 範圍,例如只掛 /app/src,讓 image 的依賴保留在原位置。代價是根目錄的設定檔、靜態素材與 lockfile 不會隨之更新;要逐一列出開發流程需要的路徑。也可評估 Compose Watch 的 sync/rebuild 分工。
另一種模式是讓容器專用 named volume 掛到 /app/node_modules,例如:
services: web: build: . working_dir: /app volumes: - .:/app - web_deps:/app/node_modules
volumes: web_deps:這只是目錄所有權示例,不能當成依賴更新機制。Docker volume 文件說明:空 volume 掛到容器原本有資料的目錄時,預設會複製既有內容;非空 volume 則保留自己的資料並遮住原內容。已用過的依賴 volume,不會因 image 重建就自動換成新版本。 volume-nocopy 等選項也會改變初始化行為。
若採用容器內安裝依賴,需由專案工作流程負責 lockfile、安裝命令、檔案權限和更新驗收;不能同時假設 image 與舊 volume 永遠一致。正式部署若不需要即時同步原始碼,先確認是否根本不該保留這個開發用 bind mount。
修好後核對檔案來源,別用刪光 volume 當驗收
修改掛載設定後,依專案流程重新建立受影響的服務,再確認 Mounts、依賴版本及最小啟動任務。只看到 node_modules 存在還不夠,它可能是舊 volume 的內容。
不要為了排查依賴就直接使用 docker compose down -v。同一專案的 volume 可能包含資料庫資料;應先確認目標 volume 的用途、可重建性與備份。這篇沒有重建服務、建立依賴 volume 或執行刪除,實際套用仍需在自己的開發環境驗收。
參考資料: