首页 > Technology > 正文

Docker 容器启动失败怎么办?12 种常见原因与修复

fenij 2026-08-11 44 Technology

docker run 下去容器没起来,docker ps -a 看到 STATUS 一片 Exited (137) / Exited (1)。这种问题在本地和 CI 里几乎天天发生。Docker 容器的启动失败原因集中在十几个固定场景,按频次从高到低查,5-10 分钟能落到具体位置。

第一步:先看容器报什么错

不要上来就 rebuild,先看 docker 自己说什么:

docker ps -a # 看 STATUS 列
docker logs container_id --tail 200
docker logs container_id --tail 200 2>&1 | grep -i 'error\|exception\|fail'

📋
看日志
docker logs
🔍
看 inspect
docker inspect
🚪
进容器
docker exec -it

没有日志(容器压根没启动到输出那一步)就上 inspect:

docker inspect container_id | grep -A 3 'Error\|State'

第二步:常见错误码速查

退出码 含义 最常见原因
0 正常退出(少见) 前台任务完成、配置写了 restart=always 错
1 应用启动失败 配置错 / 依赖缺失 / 端口占用
125 / 126 docker daemon 问题 Docker 服务没正常运行
127 命令找不到 CMD/ENTRYPOINT 拼错或文件不存在
137 OOM Killed(最常见) 内存不足被宿主机杀掉
139 段错误(segfault) 应用本身崩溃、版本不兼容
143 收到 SIGTERM 正常被 docker stop / orchestrator 终止

第三步:频次最高的几个场景

场景 1:Exited (137) — OOM Killed

最常见。容器内存超出限制被宿主机 OOM Killer 杀掉。

docker inspect container_id | grep -i oom
docker events --since='2026-08-11T00:00:00' --filter type=oom

修复:要么加 --memory 1g,要么 JVM / Node 这种运行时调小堆内存(比如 Java -Xmx512m,Node --max-old-space-size=512)。

场景 2:Exited (1) — 应用启动失败

查 docker logs 里的具体报错。常见:

  • 配置路径错(YAML / conf 文件找不到或语法错)
  • 环境变量缺失(DB_HOST / API_KEY 没传)
  • 端口被占(bind: address already in use
  • 数据库连接不上(等不到 DB ready 就起)

修法:

  • 加 HEALTHCHECK 起一段时间再 ready
  • depends_on 加 condition: service_healthy(Compose 里)
  • 改环境变量或 mount 路径

场景 3:端口冲突

宿主机端口已经被占:

lsof -i :8080 # 看谁占了
docker run -p 9090:8080 image # 改宿主机端口

场景 4:CMD 形式错误

Shell 形式 CMD npm start vs Exec 形式 CMD ["npm","start"]。Exec 形式才是标准做法,Shell 形式容易收不到 SIGTERM,docker stop 要等 10 秒超时。

场景 5:卷权限错

挂载 -v 后容器内 uid/gid 跟宿主机不一致,文件 owner 是 root,应用写日志报 Permission denied。修法:

  • 镜像里 USER 1000
  • 宿主机 chown -R 1000:1000 /data
  • 用命名卷而非 bind mount(命名卷权限由 Docker 管)

场景 6:HEALTHCHECK 没配

容器其实起来了,但应用没监听端口,orchestrator 以为它挂了。Dockerfile 加:

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/healthz || exit 1

场景 7:Secrets 进了 ENV

密码直接写在 ENV 里,docker inspect 能看到全部明文。改用 --env-file 或 Docker secrets / Vault。

场景 8:.dockerignore 没配

node_modules / .git / .env / *.pem 全被打进镜像,体积爆炸还泄密。建 .dockerignore:

node_modules
.git
.env
*.pem
*.key

第四步:进入容器内部排查

容器至少跑到了一瞬间,可以用 docker exec -it container_id /bin/sh 进去。如果进不去,就在 docker run 时加 --entrypoint /bin/sh 临时覆盖启动命令。

或者 docker run --rm -it image:tag /bin/sh 直接跳过 CMD 进去看文件系统。

第五步:K8s 场景下的容器启动失败

在 K8s 里更复杂一点:

Pod 状态 原因 排障命令
ImagePullBackOff 镜像拉不下来 kubectl describe pod
CrashLoopBackOff 应用反复崩溃 kubectl logs –previous
OOMKilled 超内存限制 kubectl describe pod 看 status
Pending 调度不到节点 kubectl describe pod 看 events
CreateContainerConfigError Secret/ConfigMap 缺失 kubectl get cm,secret

Deployment 防崩 checklist:

  • 别用 :latest,固定 tag
  • resources.requests + limits 都设
  • livenessProbe + readinessProbe 都配
  • runAsNonRoot: true,readOnlyRootFilesystem: true(tmp 用 emptyDir)

常见问题

Q:容器起来又立刻挂掉,根本来不及看日志怎么办?
A:加 --restart=no 防止自动重启覆盖掉日志;或者 docker run --entrypoint /bin/sh -it image 跳过 CMD 进去手动跑启动命令,能看到每一步输出。

Q:本地能跑,部署到服务器就起不来?
A:八成是镜像架构不匹配(Mac M1 是 arm64,服务器是 amd64)。用 docker buildx build --platform linux/amd64 多架构构建,或者服务器上用 docker run --platform linux/amd64 指定。

Q:Compose 起服务有顺序依赖怎么办?
A:用 depends_oncondition: service_healthy,配合每个服务的 HEALTHCHECK;旧版的 condition: service_started 只等启动不等 ready。

容器启动失败的原因 90% 都在上面这些场景里。先看日志、再看退出码、再对号入座,绝大多数 5 分钟能修好。如果有具体报错看不懂,贴到 fenij.com 留言里,我帮你接着分析。

相关完整手册

系统化的排查与配置思路,建议顺手收藏这几篇完整手册: