疑難排解
使用 Docker 遇到問題時,照著「看狀態 → 看日誌 → 進去看」的順序檢查,大部分問題都能很快找到原因。本頁先介紹這套檢查步驟,再用問答的方式整理最常遇到的問題:容器一啟動就停止、連不到網站、權限錯誤、建置很慢、硬碟空間不足等,每個問題都附上原因和解決方法。
遇到問題先做這三步
第一步:看狀態,容器還在跑嗎?
看 STATUS 欄位:Up 代表執行中;Exited (數字) 代表已經停止,括號裡的數字是結束代碼,下一節會說明意思。
第二步:看日誌,程式印出了什麼錯誤?
--tail 50 只顯示最後 50 行。錯誤訊息通常就在最後幾行。
第三步:進去看,檔案、設定是不是正確?
進去後可以用 ls、cat 檢查檔案,用 env 檢查環境變數。如果是 Compose 專案,改用 docker compose ps、docker compose logs <服務名稱>。
容器一啟動就停止?
容器裡的主程式結束,容器就會停止。先用 docker ps -a 看結束代碼:
| 結束代碼 | 可能原因 | 怎麼辦 |
|---|---|---|
0 |
程式正常執行完畢 | 如果它應該一直執行(例如網站),檢查啟動指令是不是跑完就結束了 |
1 |
程式出錯 | 用 docker logs 看錯誤訊息 |
127 |
找不到要執行的指令 | 檢查 CMD 的指令名稱和路徑是否正確 |
137 |
被強制停止,常見原因是記憶體不足 | 調高記憶體上限,或檢查程式是否用了太多記憶體 |
想進入一個一啟動就停止的 Image 看看裡面,可以換掉它的啟動指令:
為什麼連不到容器裡的網站?
依序檢查這四點:
- 有沒有加
-p? Dockerfile 裡的EXPOSE只是註記,要用docker run -p 8080:80或 Compose 的ports才會真的開放。 - 程式是不是只接受本機連線? 程式要監聽
0.0.0.0,不能是127.0.0.1。例如 Flask 要加--host 0.0.0.0。 - 容器之間連線用了
localhost? 在容器裡,localhost指的是容器自己。連其他容器要用容器名稱或 Compose 的服務名稱,例如db:5432。 - 容器在不同網路上? 兩個容器要在同一個自訂網路裡才能用名稱互連,見 Docker 基本操作。
如果是容器要連到你電腦上的程式,Docker Desktop 請使用 host.docker.internal 這個主機名稱。
出現 Permission denied(權限不足)?
最常見於 Linux 上使用 bind mount:容器裡的程式用一般使用者執行,但你電腦上的資料夾只有 root 能寫入。
解決方法擇一:
- 讓容器用你的身分執行:
docker run --user $(id -u):$(id -g) ... - 修改資料夾擁有者:
sudo chown -R $(id -u):$(id -g) ./data - 資料庫等資料改用 Volume,由 Docker 管理權限,最不容易出問題。
健康檢查一直失敗?
- 檢查指令不存在:例如用
curl檢查,但 Image 裡沒有安裝curl(python:3.12-slim、很多 Alpine Image 都沒有)。改用 Image 裡有的工具,範例見 Dockerfile 入門。 - 程式還沒啟動完:啟動較慢的程式,加上
start_period給它一點暖機時間。 - 看檢查結果:
docker inspect <容器名稱>輸出中的Health區塊,會列出最近幾次檢查的結果與錯誤訊息。
為什麼每次建置都很慢?
通常是快取沒有發揮作用:
- Dockerfile 順序不對:
COPY . .放在安裝套件之前,改任何程式碼都要重新安裝全部套件。先複製套件清單並安裝,最後才複製程式碼。 - 沒有
.dockerignore:node_modules、.git這類大資料夾每次都被傳進建置流程,也可能讓快取失效。
原理請看 Dockerfile 入門 的「為什麼要先複製 requirements.txt?」。
出現 exec format error?
這代表 Image 和電腦的 CPU 架構不同。例如 Apple Silicon 的 Mac 是 ARM 架構,而有些 Image 只有 Intel/AMD(amd64)版本。
- 臨時解法:指定平台,用模擬的方式執行(速度較慢):
docker run --platform linux/amd64 <Image名稱> - 根本解法:建置 Image 時同時產生兩種架構,見 Docker 常用指令速查 的「多平台」。
Windows 和 macOS 要注意什麼?
- bind mount 比較慢:檔案要跨越 Docker Desktop 背後的虛擬機,檔案很多時(例如
node_modules)會明顯變慢。Windows 使用者可以把專案放在 WSL 2 裡面,速度會快很多。 - 換行字元問題:Windows 的換行字元和 Linux 不同,會讓 shell 腳本在容器裡出現
not found的錯誤。在專案加一個.gitattributes檔,寫入*.sh text eol=lf即可。
硬碟空間不足怎麼辦?
先看看是什麼佔用了空間:
再依需要清理:
docker container prune # 刪除所有已停止的容器
docker image prune # 刪除沒有名稱的 Image(通常是舊的建置結果)
docker builder prune # 刪除建置快取
docker system prune # 一次清除以上全部
這兩個指令要特別小心
docker system prune -a會刪除所有沒有被容器使用的 Image,之後要用時必須重新下載。docker volume prune會刪除沒有被使用的 Volume,資料庫的資料可能因此永久消失。執行前先用docker volume ls確認。
參考資料
推薦影音
Have the superpower of fixing containers
簡述:Docker 官方演講,示範如何找出容器出錯的原因,並用 Docker Desktop 的工具自己修好,可以和本頁「遇到問題先做這三步」搭配。(Docker 官方)
Publishing and exposing ports
簡述:Docker 官方短片,說明 -p 和 EXPOSE 的差別,對應本頁「為什麼連不到容器裡的網站?」。(Docker 官方)
更多影片請見 影音教學。