Docker 用久以后,问题通常不在“会不会启动一个容器”,而在日常维护和排错:容器为什么退出、日志在哪里看、端口为什么不通、磁盘为什么爆了、Compose 更新为什么没生效、Swarm 服务为什么一直 Pending。

这篇文章按实际运维顺序整理:先看单机 Docker 的容器、镜像、日志、网络、存储和资源排查,再看 Compose 的项目级管理,最后看 Swarm 的集群级服务维护。

总览:Docker 排错先分清三种运行层级#

Docker 相关问题先不要急着敲命令,先判断当前应用跑在哪一层:

层级常见命令管理对象适合场景
单机 Dockerdocker rundocker psdocker logscontainer、image、volume、network单机服务、临时调试、本地开发
Docker Composedocker compose updocker compose logs一个项目里的多服务开发环境、小型部署、依赖编排
Docker Swarmdocker servicedocker stackdocker nodeservice、task、stack、node多节点集群、滚动更新、副本调度

排错时也按这个顺序看:

服务不可用
  -> 容器是否存在、是否在运行
  -> 日志里有没有启动失败或业务异常
  -> 端口映射和网络是否正确
  -> volume、配置、环境变量是否正确
  -> CPU、内存、磁盘是否打满
  -> 如果是 Compose,看 project/service 维度
  -> 如果是 Swarm,看 node/service/task 维度

一、日常巡检:先看 Docker 基本状态#

先确认 Docker daemon 是否正常:

systemctl status docker
systemctl is-enabled docker
docker version
docker info

如果 docker version 只能看到 Client,看不到 Server,通常说明 Docker daemon 没启动、当前用户没有权限,或者 Docker socket 不可用。

常用巡检命令:

docker ps
docker ps -a
docker images
docker volume ls
docker network ls
docker system df

重点看四件事:

  1. 是否有容器反复退出。
  2. 镜像、容器、volume 是否占用大量磁盘。
  3. 容器端口是否映射到预期宿主机端口。
  4. 是否存在异常多的旧容器、旧镜像、无用网络。

docker system df 很适合做磁盘占用入口,它能快速告诉你镜像、容器、本地 volume 和 build cache 大概用了多少空间。

二、容器运行:创建、启动、停止、重启#

最基本的容器运行示例:

docker run -d \
  --name nginx-demo \
  --restart unless-stopped \
  -p 8080:80 \
  nginx:stable

常用生命周期命令:

docker start nginx-demo
docker stop nginx-demo
docker restart nginx-demo
docker rm nginx-demo

如果容器已经退出,不要第一时间删除,先看状态和日志:

docker ps -a --filter name=nginx-demo
docker logs --tail=200 nginx-demo
docker inspect nginx-demo

docker inspect 输出很长,但排错时重点看:

字段关注点
State.ExitCode退出码,非 0 通常代表进程异常
State.OOMKilled是否被内存限制杀掉
State.ErrorDocker 层面的错误信息
Config.Env环境变量是否正确
HostConfig.PortBindings端口映射是否正确
Mountsvolume 或 bind mount 是否正确
NetworkSettingsIP、网络、端口信息

可以用格式化命令只取关键信息:

docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.OOMKilled}}' nginx-demo

三、日志调试:先看最近,再跟踪实时#

看容器日志:

docker logs nginx-demo
docker logs --tail=200 nginx-demo
docker logs -f --tail=100 nginx-demo
docker logs --since=30m nginx-demo

如果日志太多,不建议直接 docker logs -f 从头刷。先限制最近行数,再按时间缩小范围。

排查启动失败时,建议按这个顺序看:

  1. docker ps -a 看容器是否反复退出。
  2. docker logs --tail=200 <container> 看应用启动错误。
  3. docker inspect <container> 看环境变量、挂载、端口、退出码。
  4. docker events --since=30m 看 Docker 层事件。

docker events 很适合排查“谁重启了容器”“容器什么时候被 kill”“镜像什么时候被拉取”等问题:

docker events --since=1h

四、进入容器:调试环境、进程和文件#

进入正在运行的容器:

docker exec -it nginx-demo sh

如果镜像里有 bash:

docker exec -it nginx-demo bash

常用检查:

ps aux
env
pwd
ls -lah
cat /etc/os-release

如果容器内没有 curlnetstatping 等工具,不要急着在生产容器里安装。更推荐启动一个临时调试容器加入同一个网络:

docker run --rm -it --network container:nginx-demo nicolaka/netshoot

或者加入某个 Docker network:

docker run --rm -it --network myapp_default nicolaka/netshoot

这样可以在不污染业务镜像的情况下测试 DNS、端口、路由和 TLS。

五、端口和网络排查#

端口不通时,先确认端口映射:

docker port nginx-demo
docker ps --format 'table {{.Names}}\t{{.Ports}}\t{{.Status}}'

常见错误:

现象可能原因
宿主机访问不通没有 -p 映射,或防火墙拦截
容器之间访问不通不在同一个 Docker network
容器内访问宿主机不通Linux 上 host.docker.internal 未配置或路由不同
DNS 解析失败容器 DNS 配置、网络模式或 Compose service 名不对
端口已占用宿主机已有进程占用端口

检查网络:

docker network ls
docker network inspect bridge
docker inspect -f '{{json .NetworkSettings.Networks}}' nginx-demo

临时创建自定义网络:

docker network create app-net
docker run -d --name app --network app-net myapp:latest
docker run -d --name redis --network app-net redis:7

在同一个自定义网络里,容器可以用容器名或 Compose service 名互相访问。不要在容器之间硬编码动态 IP。

六、存储和 volume 排查#

先区分两种挂载:

类型示例特点
bind mount-v /host/data:/data直接挂宿主机目录,路径由你管理
named volume-v mysql-data:/var/lib/mysqlDocker 管理存储位置,更适合持久化数据

查看 volume:

docker volume ls
docker volume inspect mysql-data

查看容器挂载:

docker inspect -f '{{json .Mounts}}' mysql

排错重点:

  1. 宿主机目录是否存在。
  2. 文件权限、UID、GID 是否匹配容器内进程。
  3. SELinux 环境是否需要额外标签。
  4. 数据目录是否误挂成空目录,导致应用以为首次启动。
  5. 删除容器不会自动删除 named volume,数据可能仍在。

清理前一定先确认 volume 是否保存业务数据。下面这个命令会删除未被容器使用的 volume,不要在不确认的生产环境随手执行:

docker volume prune

七、镜像和磁盘清理#

查看镜像:

docker images
docker image ls --digests
docker image history nginx:stable

拉取和构建:

docker pull nginx:stable
docker build -t myapp:2026-04-29 .

磁盘紧张时先看:

docker system df
docker system df -v

常见清理命令:

docker container prune
docker image prune
docker builder prune
docker network prune

更激进的清理:

docker system prune -a

docker system prune -a 会删除未被容器使用的镜像,可能导致下次启动重新拉取镜像。生产环境建议先用 docker system df -v 看清楚,再按对象逐类清理。

一个相对稳妥的清理流程:

docker ps -a
docker system df -v
docker container prune
docker image prune
docker builder prune

如果涉及 volume,单独评估,不要和普通镜像清理混在一起。

八、资源排查:CPU、内存、OOM、健康检查#

看实时资源:

docker stats
docker stats nginx-demo

看容器是否被 OOM 杀掉:

docker inspect -f '{{.State.OOMKilled}} {{.State.ExitCode}}' nginx-demo

运行时可以加资源限制:

docker run -d \
  --name app \
  --memory 512m \
  --cpus 1.5 \
  myapp:latest

健康检查示例:

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

查看健康状态:

docker ps
docker inspect -f '{{json .State.Health}}' app

注意:健康检查失败不一定代表容器进程退出。它代表“进程还活着,但应用层探测不健康”。这对负载均衡、编排和告警很重要。

九、Docker Compose:项目级日常运行#

Compose 适合管理一个项目中的多个服务,例如 Web、MySQL、Redis、Nginx。一个最小示例:

services:
  web:
    image: nginx:stable
    ports:
      - "8080:80"
    depends_on:
      - redis
    restart: unless-stopped

  redis:
    image: redis:7
    volumes:
      - redis-data:/data
    restart: unless-stopped

volumes:
  redis-data:

启动:

docker compose up -d

查看状态:

docker compose ps
docker compose logs --tail=100
docker compose logs -f web

停止和删除项目容器:

docker compose stop
docker compose down

down 默认会删除容器和网络,但不会删除 named volume。带 -v 会删除 volume,涉及数据库时要非常谨慎:

docker compose down -v

更新镜像并重建:

docker compose pull
docker compose up -d

如果本地 Dockerfile 变了:

docker compose build
docker compose up -d

如果怀疑配置没有生效,先看最终展开配置:

docker compose config

Compose 排错常用顺序:

  1. docker compose ps 看服务状态。
  2. docker compose logs --tail=200 <service> 看业务错误。
  3. docker compose config 看变量替换后的最终配置。
  4. docker compose exec <service> sh 进入服务内部。
  5. docker compose stats 看资源消耗。
  6. docker network inspect <project>_default 看服务是否在同一网络。

十、Compose 常见坑#

环境变量没有生效。

先看 .env 是否在 compose 文件所在目录,再用:

docker compose config

确认变量是否已经被替换成预期值。

改了镜像或配置,容器还是旧的。

执行:

docker compose up -d --force-recreate

如果镜像 tag 没变,但远端镜像内容变了,先 pull:

docker compose pull
docker compose up -d --force-recreate

服务名能解析,localhost 却不通。

在容器里,localhost 指的是当前容器自己,不是另一个服务。Compose 服务之间应该用 service 名访问:

redis:6379
mysql:3306
web:8080

depends_on 不等于服务就绪。

depends_on 主要表达启动顺序,不代表数据库已经完成初始化。生产应用应该自己实现重试,或者配合 healthcheck。

十一、Docker Swarm:集群级运行模型#

Swarm 是 Docker Engine 内置的集群编排能力。它的核心对象不是单个 container,而是 service 和 task。

对象含义
node集群节点,分 manager 和 worker
service期望运行的服务定义,比如 3 个副本的 Web
taskSwarm 调度出来的具体运行任务,最终对应容器
stack用 Compose 格式部署到 Swarm 的一组服务
overlay network跨节点服务通信网络

初始化 Swarm:

docker swarm init --advertise-addr <MANAGER_IP>

查看节点:

docker node ls

创建服务:

docker service create \
  --name web \
  --replicas 3 \
  --publish 8080:80 \
  nginx:stable

查看服务和任务:

docker service ls
docker service ps web
docker service logs -f web

扩缩容:

docker service scale web=5

滚动更新:

docker service update \
  --image nginx:stable \
  --update-parallelism 1 \
  --update-delay 10s \
  web

回滚:

docker service rollback web

强制滚动重启:

docker service update --force web

十二、Swarm Stack:用 Compose 文件部署集群服务#

Swarm 可以用 docker stack deploy 部署一组服务:

services:
  web:
    image: nginx:stable
    ports:
      - "8080:80"
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure

  redis:
    image: redis:7
    deploy:
      replicas: 1

networks:
  default:
    driver: overlay

部署:

docker stack deploy -c docker-compose.yml myapp

查看:

docker stack ls
docker stack services myapp
docker stack ps myapp

删除:

docker stack rm myapp

注意:Compose 本地运行使用的是 docker compose up,Swarm stack 使用的是 docker stack deploy。两者都能读 Compose 风格的 YAML,但支持字段和运行语义并不完全一样。尤其是 deploy 字段,在 Swarm 里更关键。

十三、Swarm 排错:服务为什么没有起来#

Swarm 服务异常时,不要只看 docker ps,先看 service 和 task:

docker service ls
docker service ps --no-trunc web
docker service inspect --pretty web

常见状态:

现象排查方向
Pending没有满足条件的节点、资源不足、约束不匹配
Rejected镜像拉取失败、端口冲突、配置错误
反复重启应用启动失败、健康检查失败、资源不足
某节点没有任务节点 Drain、label 约束不匹配、资源不足
service 有副本但访问不通published port、overlay network、负载均衡、防火墙问题

查看节点状态:

docker node ls
docker node inspect --pretty <node>

把节点下线维护:

docker node update --availability drain <node>

恢复调度:

docker node update --availability active <node>

Swarm 集群还要注意 manager 数量。生产环境通常需要奇数个 manager,以维持 Raft 多数派。单 manager 适合测试,但 manager 故障后集群管理能力会受影响。

十四、常见故障速查表#

问题快速命令重点看什么
容器启动后立刻退出docker ps -adocker logsdocker inspect退出码、日志、环境变量
访问端口不通docker portdocker psss -lntp端口映射、防火墙、进程监听
容器间不通docker network inspect、临时 netshoot是否同网络、DNS、目标端口
磁盘满docker system df -v镜像、容器、volume、build cache
内存异常docker statsdocker inspectOOMKilled、内存限制、进程占用
Compose 配置不对docker compose config环境变量替换、最终配置
Compose 服务异常docker compose psdocker compose logs服务状态、依赖、日志
Swarm 服务 Pendingdocker service ps --no-trunc约束、资源、节点状态
Swarm 滚动更新失败docker service psdocker service rollback新镜像、健康检查、回滚策略

十五、建议保留的一组日常命令#

单机 Docker:

docker ps -a
docker logs --tail=200 <container>
docker inspect <container>
docker stats
docker system df -v
docker events --since=30m

Compose:

docker compose ps
docker compose logs --tail=200
docker compose config
docker compose pull
docker compose up -d
docker compose exec <service> sh

Swarm:

docker node ls
docker service ls
docker service ps --no-trunc <service>
docker service logs -f <service>
docker stack services <stack>
docker stack ps <stack>

总结#

Docker 排错的核心不是背命令,而是分层:

  1. 单机 Docker 先看 container、image、network、volume、resource。
  2. Compose 先看 project、service、最终配置和服务间网络。
  3. Swarm 先看 node、service、task、stack 和调度约束。
  4. 有副作用的清理命令要慢一点,尤其是 volume 和 system prune -a
  5. 日志、inspect、stats、network inspect 是最常用的四类证据。

日常维护时,建议把“状态检查、日志检查、资源检查、磁盘清理、配置备份、更新回滚”做成固定流程。这样遇到问题时,不会在一堆容器和命令之间乱撞,而是按层级把问题一步步缩小。

参考资料#