首页 >
博客 > docker容器启动失败排查指南
← 返回工具首页
Docker 启动失败?我排查了10个案例总结的实战指南
🐳 Docker 启动失败?我排查了10个案例总结的实战指南
你有没有过这种经历:本地跑得好好的容器,一部署就报错;或者昨天还正常的服务,今天突然起不来?本文从10个真实翻车场景出发,梳理5类最常见的 Docker 启动失败原因,每个都带诊断命令 + 修复步骤,拿来就能用。
---
案例1:端口已被宿主机其他进程占用
最经典的"昨天还能跑,今天就不行"——99%是另一个服务抢了你的端口。
Error: Cannot start container: ports are already allocated
docker ps -a --format "{{.Names}}\t{{.Ports}}"
lsof -i :8080
ss -tlnp | grep 8080
两种思路:停掉占用端口的进程,或者换端口。
kill $(lsof -t -i:8080)
docker run -d -p 8081:80 nginx
💡 如果是 Docker 内部端口冲突(比如两个容器都声明 expose: 80),不会报这个错。这个错误一定是宿主机端口被占用。
---
案例2:镜像名称写错 / 私有仓库拉不到
Pull 镜像的时候悄无声息地失败,或者 tag 写错了导致找不到镜像。
Error: pull access denied, repository does not exist or may require authorization
Error: manifest unknown
docker images | grep <image_name>
docker pull <image_name>:<tag>
docker login <registry.example.com>
docker pull nginx:latest
docker pull nginx:alpine
docker pull nginx:1.27.0
docker pull registry.example.com/myproject/api:v2.3.1
docker login registry.example.com
⚠️ latest 标签不保证是"最新稳定版",很多镜像维护者根本不怎么更新 latest,导致你 CI 拉到的可能是一年前的版本。生产环境一定要写死具体 tag。
---
案例3:网络模式配置错误导致容器互通失败
容器启动了,进程也在跑,但容器之间互相访问不到,比如 MySQL 容器明明起来了,API 容器却连不上。
Error: connect ECONNREFUSED 172.18.0.2:3306
docker network ls
docker inspect <container_name> | jq '.[0].NetworkSettings.Networks'
docker exec -it <container_name> ping <target_container>
docker exec -it web curl http://db:3306
docker network inspect bridge
用 docker-compose 的 networks 把相关容器放进同一个网络,这是最推荐的方式:
version: "3.8"
services:
web:
image: myapp:latest
networks:
- backend
db:
image: mysql:8
networks:
- backend
networks:
backend:
driver: bridge
docker network create mynet
docker network connect mynet <container_a>
docker network connect mynet <container_b>
💡 Docker 默认用 bridge 网络,但同一个宿主机上的两个容器默认情况下不在同一个网络里,需要通过 --network 或 docker-compose 显式声明才能互通。
---
案例4:挂载目录权限不够,容器里写不了文件
容器启动参数加了 -v /data:/app/data,但应用启动时报"Permission denied",或者构建时文件所有者是 root。
Permission denied: '/app/data/config.yml'
EACCES: permission denied, open '/app/data/logs/app.log'
docker inspect <container_name> | jq '.[0].Mounts'
ls -la /data
id
docker exec -it <container_name> id
docker exec -it <container_name> whoami
sudo mkdir -p /data
sudo chown -R 1000:1000 /data
docker run -v /data:/app/data -u 1000 myapp:latest
setfacl -R -m u:1000:rwX /data
🔑 容器内 root(UID 0)和宿主机 root 是不同的,但在 volume 挂载场景下,宿主机 root 权限会渗透进去——所以会出现宿主机 root 创建的文件,容器内非 root 用户无法写入的情况。
---
案例5:ENTRYPOINT / CMD 脚本语法错误
Dockerfile 写得很标准,镜像也构建成功了,但容器一启动就退出,日志里只有一个模糊的 exit code。
Error: spawner failed to start: exit status 1
docker: Error response from daemon: oci runtime error: exit status 1
docker logs <container_name> --tail 50
docker wait <container_name>
docker inspect <container_name> | jq '.[0].State'
先看一个典型的错误 Dockerfile:
CMD python app.py --port 8080
CMD ["python", "app.py", "--port", "8080"]
ENTRYPOINT python app.py
ENTRYPOINT ["python", "app.py"]
如果用了 shell 脚本做入口点,注意脚本里要有 exec "$@" 来传递信号:
set -e
echo "Starting app with args: $@"
exec "$@"
---
案例6:docker-compose.yml 配置格式踩坑
docker-compose 语法版本不对,或者缩进、空格、引号问题导致配置解析失败。
ERROR: yaml.scanner.ScannerError: while scanning a simple key
ERROR: service 'web' must be a mapping
docker-compose config --quiet
docker-compose --version
services:
web:
image: nginx
ports:
- "8080:80"
ports:
- 8080:80
version: "3.8"
services:
web:
depends_on:
- db
environment:
- DB_HOST=db
⚠️ docker-compose v2 开始默认用空格缩进,tab 一定会报错。另外 docker-compose config 能把最终合并后的配置输出来,怀疑有覆盖冲突时用这个命令非常管用。
---
案例7:容器退出后想看日志却不知道从哪看
容器跑了几秒就退出了,docker logs 拿不到任何内容,因为进程在启动脚本里又起了子进程。
container is not running
docker ps -a | grep <container_name>
docker start -ia <container_name>
docker inspect <container_name> | jq '.[0].State'
docker top <container_name>
容器已经退出了?不要慌,先找残余信息:
docker logs <container_name> --tail 200 --details
docker commit <container_name> temp_debug_image
docker run -it --rm temp_debug_image /bin/sh
docker run --rm -it <image_name> /bin/sh
✅ 小技巧:docker-compose up --abort-on-container-exit 可以让 docker-compose 在任何一个容器退出时立即停止并显示输出,排查 entrypoint 脚本问题时非常有用。
---
案例8:docker inspect 挖出隐藏配置问题
docker inspect 是被严重低估的排查工具。容器启动失败时,90%的隐藏问题都能从这里找到答案。
docker inspect <container_name> | jq '.[0].Config.Env'
docker inspect <container_name> | jq '.[0].Config.Cmd'
docker inspect <container_name> | jq '.[0].Config.Entrypoint'
docker inspect <container_name> | jq '.[0].Mounts'
docker inspect <container_name> | jq '.[0].HostConfig.RestartPolicy'
docker inspect <container_name> | jq '{
State: .[0].State,
Env: .[0].Config.Env,
Cmd: .[0].Config.Cmd,
Mounts: .[0].Mounts,
NetworkSettings: .[0].NetworkSettings.Networks,
RestartPolicy: .[0].HostConfig.RestartPolicy
}'
💡 jq 是神器,上面的组合拳可以一次性拿到所有关键配置,省去来回敲命令的时间。macOS/Linux 安装:brew install jq 或 apt install jq。
---
案例9:OOMKilled — 内存限制太小被 kill
容器进程明显在跑,但一会儿就没了。查日志什么都没有,因为进程被宿主机直接 kill 了。
Killed
docker: Error response from daemon: Cannot kill container: ...
exit code 137(128 + 9,OOM SIGKILL 的标准退出码)
docker inspect <container_name> | jq '.[0].State'
dmesg | grep -i "killed process" | tail 10
docker run -d --memory=512m --memory-swap=1g myapp:latest
docker run -d --memory="" myapp:latest
🚨 退出码 137 = OOM(SIGKILL),128 + 9。退出码 143 = SIGTERM(正常停止)。退出码 1 = 应用自己报错退出。搞清楚这三个码,能省一半排查时间。
---
案例10:Docker daemon 本身挂了
最隐蔽的情况:所有命令都报错,但你以为是你自己的配置问题,其实是 Docker 服务本身崩了。
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
sudo systemctl status docker
sudo service docker status
ls -la /var/run/docker.sock
sudo systemctl restart docker
df -h /var/lib/docker
docker system prune -af --volumes
✅ 建议:生产环境的 Docker 服务用 systemctl enable docker 确保开机自启,并且定期监控 /var/lib/docker 的磁盘使用率。
---
🚀 快速排查流程图(总结)
下次容器起不来,按这个顺序走,基本能覆盖 90% 的坑:
1. 看容器状态 → docker ps -a
2. 看退出码 → docker inspect | jq '.[0].State.ExitCode'
├─ 退出码 0 = 正常退出,看 CMD/ENTRYPOINT
├─ 退出码 1 = 应用报错 → docker logs
├─ 退出码 137 = OOM → 调大 --memory
└─ 退出码 143 = SIGTERM → 检查 restart policy
3. 连容器都建不起来 → 查 docker daemon systemctl status docker
4. 镜像问题 → docker pull + docker images
5. 端口问题 → lsof -i :端口
6. 网络互通 → docker network inspect
7. 权限问题 → docker inspect Mounts + 宿主机 ls -la
8. YAML 问题 → docker-compose config
---
首发于 CloverTools · 助你少加班,多摸鱼 🐟
常见问题
Q: 如何使用 docker容器启动失败排查指南 相关工具?
A: 这类工具一般有明确的输入框和输出框,按提示输入内容,点击对应按钮即可得到结果。建议先用简单示例测试功能是否正常,再处理实际数据。
Q: docker容器启动失败排查指南 适合在什么场景使用?
A: 根据具体工具类型决定。格式转换工具适合处理第三方数据,编码工具适合加密传输,压缩工具适合文件上传前处理。多积累工具使用经验,遇到问题时能快速判断用哪个工具解决。
Q: 有没有更好的替代工具?
A: 不同工具有不同侧重,重点是理解原理。可以同时安装多个类似工具,实际使用中对比效果,选择最顺手的一个。随着使用经验增加,你也能判断工具的好坏。