01 常见问题排查
按「现象 → 原因 → 解决」整理 Docker 使用中最高频的问题。排查任何问题前,先记住万能三板斧:
docker compose ps # 1. 看状态
docker compose logs 服务名 # 2. 看日志
docker compose config # 3. 看最终生效的配置
1. 容器启动即退出(Exited)
现象:docker ps -a 里 STATUS 显示 Exited (1) xxx ago。
排查:先看日志找报错:
docker logs 容器名
常见原因:
| 日志特征 | 原因 | 解决 |
|---|---|---|
| 应用报错堆栈 | 代码/配置错误 | 按堆栈修 |
exec format error | 镜像架构不对(ARM 机器跑了 x86 镜像) | 拉对应架构镜像,或构建时指定 --platform linux/amd64 |
| 没有任何日志,Exited (0) | 容器内没有前台进程,跑完就退了 | CMD 必须是前台运行的命令(如 nginx -g "daemon off;") |
MYSQL_ROOT_PASSWORD ... not set | 必填环境变量没传 | 补上环境变量 |
2. 端口相关
端口被占用
现象:Bind for 0.0.0.0:8080 failed: port is already allocated 或 address already in use。
解决:找到占用者,换端口或停掉它:
# Linux
sudo lsof -i :8080
# 或
sudo ss -tulnp | grep 8080
# Windows (PowerShell)
netstat -ano | findstr :8080
端口通了但访问不到服务
现象:容器 Up、端口映射也在,但浏览器访问不通。
最常见原因:容器里的服务监听了 127.0.0.1 而不是 0.0.0.0。
# 验证:进容器里能通,外面不通,基本就是这个问题
docker exec -it 容器名 sh
wget -qO- http://localhost:8000
解决:把服务的监听地址改成 0.0.0.0(uvicorn 加 --host 0.0.0.0,Node 服务 listen 时传 0.0.0.0,等等)。
3. 容器互联不通
现象:应用容器连不上数据库容器,报 Connection refused 或 Name or service not known。
排查清单:
- 连接地址写的是服务名而不是
localhost吧?容器里的localhost是容器自己 - 两个容器在同一个网络吗?
docker network inspect 网络名看看 - 用
docker run手动起的容器,在默认 bridge 网络里不能用容器名互访——建自定义网络或改用 Compose - 数据库真的就绪了吗?MySQL 首次初始化要几十秒,用
depends_on+condition: service_healthy
# 在应用容器里测试连通性
docker compose exec api ping mysql
docker compose exec api sh -c "wget -qO- telnet://mysql:3306 || true"
4. 数据问题
改了 MySQL 密码环境变量但不生效
环境变量只在数据卷为空的首次初始化时生效。已初始化过的库,改 compose 里的密码变量没用。要么进容器用 SQL 改密码,要么(测试环境)docker compose down -v 删卷重来。
容器删了数据没了
没挂数据卷。数据类容器(MySQL/Redis/MinIO 等)必须给数据目录配卷,参考 数据卷与网络。
挂载目录后容器里是空的 / 文件不见了
绑定挂载会用宿主机目录覆盖容器内目录。比如把空目录挂到 /usr/share/nginx/html,容器里原来的欢迎页就被「盖住」了。这是特性不是 bug:想初始化内容用命名卷(首次挂载会把镜像内容拷进卷),或者提前把文件放进宿主机目录。
Permission denied(挂载目录没权限)
容器内进程的 UID 和宿主机目录属主不一致。解决:
# 看容器用什么 UID 跑
docker exec 容器名 id
# 把宿主机目录 chown 成这个 UID
sudo chown -R 1000:1000 /data/mydir
5. 磁盘爆满
现象:服务器磁盘 100%,罪魁祸首常是 Docker。
# 看 Docker 占了多少
docker system df
# 一键清理:停止的容器 + 无用网络 + 悬空镜像 + 构建缓存
docker system prune
# 更狠:连所有未被使用的镜像一起删
docker system prune -a
# 容器日志也常是大头,找出大日志文件
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail
预防:所有服务配日志上限(max-size: "10m"),定期跑 docker system prune。
6. 构建问题
拉取镜像超时
failed to resolve source metadata / i/o timeout——网络问题,配镜像加速(见 安装Docker 第 4 节)。
构建时 pip/npm 下载慢或失败
在 Dockerfile 里用国内源:
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
RUN npm ci --registry=https://registry.npmmirror.com
改了代码但构建没变化(缓存问题)
确认部署命令带了 --build;仍然不对就强制不用缓存:
docker compose build --no-cache 服务名
docker compose up -d
7. Compose 配置报错
| 报错 | 原因 |
|---|---|
yaml: line N: mapping values are not allowed | YAML 缩进错误,冒号后面少了空格 |
The "XXX" variable is not set | .env 里没定义这个变量(或 .env 不在 compose.yaml 同目录) |
service "xxx" depends on undefined service | depends_on 写了不存在的服务名 |
port is already allocated | 端口冲突,见第 2 节 |
排查利器:docker compose config,它会在启动前就把语法错误、变量缺失暴露出来。
8. 实在不行的终极重置
测试环境专用(会删数据,生产环境三思):
docker compose down -v # 停掉并删卷
docker compose up -d --build # 从零重建
小结
- 遇到问题先
ps→logs→config,九成问题日志里有答案 - 高频四坑:监听
127.0.0.1、用localhost连别的容器、没挂数据卷、磁盘被日志塞满 - 环境变量初始化只在数据卷为空时生效
- 定期
docker system prune+ 日志限额,磁盘才不会爆
配合 02-常用命令速查 使用效果更佳。