13 10 月 2026

Docker 用起来方便,出问题时也容易懵:容器起不来、端口访问不了、磁盘莫名其妙满了、容器删了数据也没了。

这篇按故障现象讲排查方法,配合可直接执行的命令。

容器出问题前先备份数据卷。财富云计算 的云服务器支持快照;内部服务、测试环境可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。

一、容器启动失败

排查步骤

# ① 看容器状态
docker ps -a
# STATUS 列会显示 Exited (1) 等,括号里是退出码

# ② 看日志(最重要)
docker logs 容器名
docker logs --tail 100 容器名
docker logs -t 容器名          # 带时间戳

# ③ 看详细信息
docker inspect 容器名
# 关注 State 部分:Error、ExitCode、OOMKilled

常见退出码

退出码含义
0正常退出
1程序错误
125Docker 命令错误(如端口被占)
126命令不可执行(权限问题)
127命令找不到
137被 SIGKILL(OOM 或 docker kill)
139段错误
143被 SIGTERM(docker stop)

典型原因与解决

① 容器启动后立即退出

docker logs 容器名
# 常见:配置文件错误、依赖缺失、端口冲突、入口命令执行完就结束

注意:容器的主进程结束,容器就退出。比如 docker run ubuntu 不带交互命令会立即退出。

# 保持运行
docker run -dit ubuntu
# 或跑一个常驻命令
docker run -d nginx

② 端口被占用

Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
ss -tulnp | grep :80
docker ps                  # 是不是已有容器占用
# 解决:停掉占用的,或换端口
docker run -d -p 8080:80 nginx

③ 存储卷挂载失败

docker logs 容器名
# 常见:宿主机目录不存在、权限不足、SELinux 拦截
# SELinux 系统加 :z 或 :Z
docker run -v /data:/app:z myapp

④ 内存不足被杀(OOMKilled)

docker inspect 容器名 | grep -i oom
# "OOMKilled": true
dmesg | grep -i oom

解决:限制并调整内存:

docker run -m 512m myapp
docker update --memory 512m 容器名

⑤ 镜像或配置错误

docker compose config          # 检查 compose 文件
docker compose logs

二、端口访问不了

排查流程

# ① 容器在不在跑
docker ps

# ② 端口映射对不对
docker port 容器名
docker ps                       # 看 PORTS 列
# 0.0.0.0:8080->80/tcp   表示映射所有地址
# 127.0.0.1:8080->80/tcp 表示只映射本地

# ③ 容器内服务监听地址
docker exec 容器名 ss -tulnp
# ⚠️ 常见坑:容器内服务只监听 127.0.0.1,外部访问不到
# 要改成 0.0.0.0

# ④ 宿本机能不能访问
curl http://127.0.0.1:8080

# ⑤ 从外部访问
curl http://服务器IP:8080

# ⑥ 防火墙
ufw status
iptables -L -n | grep DOCKER

常见坑

坑 1:容器内服务监听 127.0.0.1

很多程序默认只监听 localhost,容器内也一样。要改程序配置监听 0.0.0.0。

# 检查
docker exec app ss -tulnp
# tcp LISTEN 0 128 127.0.0.1:3000   ← 有问题
# tcp LISTEN 0 128 0.0.0.0:3000     ← 正常

坑 2:Docker 绕过 ufw 防火墙

Docker 会直接写 iptables,你在 ufw 里 deny 的端口,容器映射后照样能访问。

# 验证
ufw deny 8080
curl http://服务器IP:8080     # 仍能访问 ← Docker 绕过

解决:

# 方案一(推荐):容器只映射到本地,用宿主机 Nginx 反代
docker run -d -p 127.0.0.1:8080:80 nginx

# 方案二:禁用 Docker 的 iptables
# /etc/docker/daemon.json
{"iptables": false}
systemctl restart docker
# ⚠️ 副作用:容器可能无法访问外网

坑 3:映射写反了

-p 8080:80     # 宿主机 8080 → 容器 80(正确顺序:宿主:容器)

坑 4:容器间用 localhost 互访

容器内的 localhost 是容器自己,不是宿主机,也不是其他容器。

# compose 中用服务名互访
environment:
  DB_HOST: db          # 用服务名,不是 localhost
  REDIS_URL: redis://cache:6379

三、磁盘空间爆满

排查

# ① 看 Docker 占用
docker system df
docker system df -v          # 详细

# ② 看具体哪部分大
du -sh /var/lib/docker/*
du -sh /var/lib/docker/containers/*      # 容器日志通常在这
du -sh /var/lib/docker/volumes/*
du -sh /var/lib/docker/overlay2/*

常见元凶

① 容器日志(最常见)

# 找大日志
find /var/lib/docker/containers -name "*-json.log" -size +100M -exec ls -lh {} \;

# 清空(不删文件)
truncate -s 0 /var/lib/docker/containers/容器ID/*-json.log

根治:限制日志大小

// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
systemctl restart docker
⚠️ 只对新建容器生效,已有容器需要重建。

② 无用镜像和容器

docker images                # 看看有多少 <none> 的悬空镜像
docker ps -a                 # 有多少 Exited 的容器

docker container prune       # 清理停止的容器
docker image prune -a        # 清理无用镜像
docker volume prune          # 清理未使用的卷(⚠️ 注意数据安全)
docker network prune
docker system prune -a       # 全清

③ 数据卷里的业务数据

docker system df -v | grep -A 5 "Local Volumes"
du -sh /var/lib/docker/volumes/*

清理业务数据(日志、上传文件、数据库 binlog)。

④ build 缓存

docker builder prune
docker builder prune -a

预防措施

# 定期清理(crontab)
0 3 * * * docker system prune -f --filter "until=168h"    # 清理 7 天前的

四、数据丢失

常见原因

  1. 容器删了数据就没了(没挂载卷)
  2. docker compose down -v 删了数据卷
  3. volume prune 误删
  4. 重装/清理 Docker

预防

# ① 数据必须挂载卷
docker run -d -v db-data:/var/lib/mysql mysql:8
# 而不是让数据留在容器里

# ② 定期备份卷
docker run --rm -v myapp_db-data:/data -v $(pwd):/backup \
  alpine tar -czf /backup/db-$(date +%F).tar.gz /data

# ③ 恢复
docker run --rm -v myapp_db-data:/data -v $(pwd):/backup \
  alpine tar -xzf /backup/db-2026-10-13.tar.gz -C /

备份脚本:

#!/bin/bash
DATE=$(date +%F)
BACKUP=/backup/docker
mkdir -p $BACKUP

for vol in $(docker volume ls -q); do
    docker run --rm -v $vol:/data -v $BACKUP:/backup \
      alpine tar -czf /backup/$vol-$DATE.tar.gz /data
done

find $BACKUP -name "*.tar.gz" -mtime +14 -delete

误删后怎么办

如果没备份:

  • 容器还在(只是停止):用 docker cp 把数据拷出来

    docker cp 容器名:/var/lib/mysql ./mysql-backup
  • 容器已删但卷还在:卷不会被 docker rm 删除,检查 docker volume ls
  • 真的没了:只能从应用层面的备份恢复

五、容器网络问题

容器内无法访问外网

docker exec 容器名 ping 8.8.8.8
docker exec 容器名 curl https://example.com

原因与解决:

# ① 检查 DNS
docker exec 容器名 cat /etc/resolv.conf
# 可指定 DNS
docker run --dns 8.8.8.8 myapp

# ② 检查 IP 转发
sysctl net.ipv4.ip_forward      # 应为 1
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf && sysctl -p

# ③ 检查 iptables NAT
iptables -t nat -L POSTROUTING -n
# 应有 MASQUERADE 规则

# ④ 重启 Docker 重建规则
systemctl restart docker

容器间无法互访

# ① 确认在同一网络
docker network inspect 网络名

# ② 用服务名/容器名访问,不是 IP(IP 会变)
# ③ compose 环境确认服务名正确
docker compose exec app ping db

六、性能问题

容器占用资源过高

docker stats                     # 实时
docker stats --no-stream         # 一次

限制资源:

# 运行时限制
docker run -d --memory=512m --cpus=1 myapp

# 更新已有容器
docker update --memory 512m --cpus 1 容器名

宿主机被容器拖垮

# 看谁在吃资源
docker stats

# 限制所有容器:在 compose 里配 deploy.resources.limits

IO 性能差

# 挂载方式影响性能
# bind mount 通常比 volume 略快
# 大量小文件读写建议用 volume

七、镜像与构建问题

拉取镜像慢或失败

# ① 配镜像加速
nano /etc/docker/daemon.json
{"registry-mirrors": ["https://docker.m.daocloud.io"]}
systemctl restart docker

# ② 检查网络
curl -I https://registry-1.docker.io/v2/

# ③ 查看 Docker 日志
journalctl -u docker -n 50

构建失败

docker build .                   # 不加 --quiet 能看到完整输出
docker build --no-cache .        # 不用缓存重新构建
docker build --progress=plain .  # 详细输出

常见:

问题解决
网络不通(npm/pip 装不上)换国内源,或 --network=host
文件找不到检查 .dockerignore 和 COPY 路径
权限错误加 USER root 或改文件权限
缓存导致没更新--no-cache
构建上下文太大配 .dockerignore

镜像太大

docker images

优化:

# ✅ 用 alpine 基础镜像
FROM node:18-alpine

# ✅ 多阶段构建
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

# ✅ 合并 RUN 减少层数,清理缓存
RUN apt update && apt install -y curl \
    && rm -rf /var/lib/apt/lists/*

八、Docker 服务本身的问题

Docker 无法启动

systemctl status docker
journalctl -u docker -n 100

常见:

报错原因解决
failed to start daemon配置错误检查 /etc/docker/daemon.json 语法
cannot connect to the Docker daemon服务没起 / 权限systemctl start docker,加用户到 docker 组
存储驱动错误文件损坏恢复或重装
磁盘满—清理空间

daemon.json 语法错误是常见原因,用 jq 检查:

jq . /etc/docker/daemon.json

重置 Docker(危险操作)

# ⚠️ 会删除所有容器、镜像、卷
systemctl stop docker
rm -rf /var/lib/docker
systemctl start docker

九、排查速查表

# 容器起不来
docker ps -a                     看状态和退出码
docker logs 容器名               看日志
docker inspect 容器名 | grep -iE "error|oom"    看错误

# 端口不通
docker port 容器名               看映射
docker exec 容器名 ss -tulnp     看容器内监听(是否 0.0.0.0)
curl http://127.0.0.1:端口       本机测
ss -tulnp                        宿主机端口
ufw status                       防火墙

# 磁盘满
docker system df -v              占用明细
du -sh /var/lib/docker/containers/*   日志
docker system prune -a           清理

# 网络
docker exec 容器名 ping 8.8.8.8  外网
docker network inspect 网络名     容器网络
sysctl net.ipv4.ip_forward       转发

# 资源
docker stats                     实时占用
docker update --memory 512m 容器 限制

十、日常维护清单

  • [ ] 配置日志大小限制(log-opts)
  • [ ] 定期清理无用镜像容器(crontab + prune)
  • [ ] 数据卷定期备份
  • [ ] 监控磁盘占用
  • [ ] 镜像定期更新(安全补丁)
  • [ ] 容器资源限制
  • [ ] 不用 latest 标签,用固定版本
  • [ ] 敏感信息不写进镜像

容器故障多与数据卷和端口相关,做好备份和映射规划能省很多麻烦。财富云计算 的云服务器支持快照,做危险操作(清理、升级)前先打快照;内部服务、测试环境可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。

相关阅读:

  • 《Docker 安装与基础命令》
  • 《Docker Compose 编排实战》
  • 《服务器资源排查:CPU / 内存 / 磁盘 / 带宽》
延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:Docker Compose 编排实战:一条命令启动整套服务
  2. 下一篇:多游戏共存一台服务器怎么配置:端口、内存、带宽全规划
发表评论 3

取消回复