Docker 日常维护、运行调试与排错教程:从 Compose 到 Swarm

Docker 用久以后,问题通常不在“会不会启动一个容器”,而在日常维护和排错:容器为什么退出、日志在哪里看、端口为什么不通、磁盘为什么爆了、Compose 更新为什么没生效、Swarm 服务为什么一直 Pending。
这篇文章按实际运维顺序整理:先看单机 Docker 的容器、镜像、日志、网络、存储和资源排查,再看 Compose 的项目级管理,最后看 Swarm 的集群级服务维护。
总览:Docker 排错先分清三种运行层级#
Docker 相关问题先不要急着敲命令,先判断当前应用跑在哪一层:
| 层级 | 常见命令 | 管理对象 | 适合场景 |
|---|---|---|---|
| 单机 Docker | docker run、docker ps、docker logs | container、image、volume、network | 单机服务、临时调试、本地开发 |
| Docker Compose | docker compose up、docker compose logs | 一个项目里的多服务 | 开发环境、小型部署、依赖编排 |
| Docker Swarm | docker service、docker stack、docker node | service、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
重点看四件事:
- 是否有容器反复退出。
- 镜像、容器、volume 是否占用大量磁盘。
- 容器端口是否映射到预期宿主机端口。
- 是否存在异常多的旧容器、旧镜像、无用网络。
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.Error | Docker 层面的错误信息 |
Config.Env | 环境变量是否正确 |
HostConfig.PortBindings | 端口映射是否正确 |
Mounts | volume 或 bind mount 是否正确 |
NetworkSettings | IP、网络、端口信息 |
可以用格式化命令只取关键信息:
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 从头刷。先限制最近行数,再按时间缩小范围。
排查启动失败时,建议按这个顺序看:
docker ps -a看容器是否反复退出。docker logs --tail=200 <container>看应用启动错误。docker inspect <container>看环境变量、挂载、端口、退出码。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
如果容器内没有 curl、netstat、ping 等工具,不要急着在生产容器里安装。更推荐启动一个临时调试容器加入同一个网络:
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/mysql | Docker 管理存储位置,更适合持久化数据 |
查看 volume:
docker volume ls
docker volume inspect mysql-data
查看容器挂载:
docker inspect -f '{{json .Mounts}}' mysql
排错重点:
- 宿主机目录是否存在。
- 文件权限、UID、GID 是否匹配容器内进程。
- SELinux 环境是否需要额外标签。
- 数据目录是否误挂成空目录,导致应用以为首次启动。
- 删除容器不会自动删除 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 排错常用顺序:
docker compose ps看服务状态。docker compose logs --tail=200 <service>看业务错误。docker compose config看变量替换后的最终配置。docker compose exec <service> sh进入服务内部。docker compose stats看资源消耗。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 |
| task | Swarm 调度出来的具体运行任务,最终对应容器 |
| 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 -a、docker logs、docker inspect | 退出码、日志、环境变量 |
| 访问端口不通 | docker port、docker ps、ss -lntp | 端口映射、防火墙、进程监听 |
| 容器间不通 | docker network inspect、临时 netshoot | 是否同网络、DNS、目标端口 |
| 磁盘满 | docker system df -v | 镜像、容器、volume、build cache |
| 内存异常 | docker stats、docker inspect | OOMKilled、内存限制、进程占用 |
| Compose 配置不对 | docker compose config | 环境变量替换、最终配置 |
| Compose 服务异常 | docker compose ps、docker compose logs | 服务状态、依赖、日志 |
| Swarm 服务 Pending | docker service ps --no-trunc | 约束、资源、节点状态 |
| Swarm 滚动更新失败 | docker service ps、docker 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 排错的核心不是背命令,而是分层:
- 单机 Docker 先看 container、image、network、volume、resource。
- Compose 先看 project、service、最终配置和服务间网络。
- Swarm 先看 node、service、task、stack 和调度约束。
- 有副作用的清理命令要慢一点,尤其是 volume 和
system prune -a。 - 日志、inspect、stats、network inspect 是最常用的四类证据。
日常维护时,建议把“状态检查、日志检查、资源检查、磁盘清理、配置备份、更新回滚”做成固定流程。这样遇到问题时,不会在一堆容器和命令之间乱撞,而是按层级把问题一步步缩小。