适用人群:Linux 运维新手、后端开发、DevOps 初学者
1. 核心概念:区分"Docker 服务"与"容器"
在开始之前,需要明确两个概念,避免混淆:
- Docker 服务 (Daemon) :指 Docker 引擎本身(
dockerd)。如果它挂了,所有容器都会停止。 - 容器 (Container):指运行在 Docker 里的具体应用(如 Nginx、MySQL、Nacos、你的业务代码)。
新手提示:通常我们说"查看 Docker 运行",既可能指查看引擎是否活着,也可能指查看里面的业务容器是否正常。下文将分开讲解。
2. 基础篇:查看 Docker 引擎状态
2.1 检查 Docker 引擎是否存活
这是最基础的命令,用于确认服务器上的 Docker 软件本身是否在运行。
bash
# 查看详细的服务状态(推荐)
sudo systemctl status docker
# 快速判断(脚本常用)
systemctl is-active docker
输出解读:
active (running):正常,Docker 引擎正在运行。inactive (dead):未启动,需要执行sudo systemctl start docker。failed:启动失败,需要查看日志排查:sudo journalctl -u docker.service -n 50。
2.2 验证 Docker 客户端连接
如果 systemctl 显示正常,但执行 docker 命令报错,可以用此命令验证。
bash
docker info
输出解读:
- 如果输出一大堆关于 Containers、Images、Storage Driver 的信息,说明连接正常。
- 如果报错
Cannot connect to the Docker daemon,说明服务虽然启动了但 socket 文件有问题或权限不足。此时可尝试将当前用户加入 docker 用户组:sudo usermod -aG docker $USER,然后重新登录。
2.3 Docker 服务管理命令速查
| 操作 | 命令 | 说明 |
|---|---|---|
| 启动 Docker | sudo systemctl start docker |
启动 Docker 引擎 |
| 停止 Docker | sudo systemctl stop docker |
停止引擎(会停止所有容器) |
| 重启 Docker | sudo systemctl restart docker |
修改配置后常用 |
| 设置开机自启 | sudo systemctl enable docker |
防止服务器重启后服务丢失 |
| 查看 Docker 日志 | sudo journalctl -u docker.service |
排查引擎启动失败等问题 |
3. 进阶篇:查看与管理容器(业务服务)
这是日常工作中最高频的操作区域。
3.1 查看容器运行状态(黄金命令)
不要只用 docker ps,建议养成使用格式化输出的习惯,信息更直观。
bash
# 查看所有容器(包括已退出的),并格式化输出
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}"
参数拆解:
-a/--all:显示所有容器,不仅仅是正在运行的。--format:自定义输出列。这里我们按顺序展示:容器ID、名字、状态、镜像、端口映射。
输出示例与解读:
| CONTAINER ID | NAMES | STATUS | IMAGE | PORTS |
|---|---|---|---|---|
| a1b2c3d4e5f6 | nginx-web | Up 2 hours | nginx:latest | 0.0.0.0:80->80/tcp |
| 1854247741c4 | mysql-db | Exited (1) 5 mins ago | mysql:8.0 | 3306/tcp |
| f9e8d7c6b5a4 | app-backend | Restarting (1) 10s ago | myapp:v1 | ... |
状态关键字速查表:
| 状态关键字 | 含义 | 健康度 |
|---|---|---|
Up x hours |
正在运行中 | 正常 |
Up x hours (healthy) |
正在运行且通过健康检查 | 非常健康 |
Up x seconds |
刚启动不久 | 需观察是否稳定 |
Exited (0) |
正常退出(任务完成或手动停止) | 视情况而定 |
Exited (1) / (137) |
异常退出(报错或被系统杀掉) | 异常 |
Restarting |
正在反复重启 | 严重异常 |
Created |
已创建但未启动 | 未运行 |
Paused |
已暂停 | 需确认 |
Dead |
无法恢复 | 异常 |
3.2 快速筛选特定状态的容器
当服务器上有几十个容器时,直接筛选更高效。
bash
# 1. 只看"活着"的容器(默认等价于 docker ps)
docker ps
# 2. 只看"死掉"的容器(Exited)
docker ps -a --filter "status=exited"
# 3. 只看"反复重启"的容器(最危险)
docker ps -a --filter "status=restarting"
# 4. 只看"已创建未启动"的容器
docker ps -a --filter "status=created"
3.3 查看容器日志(排查神器)
当发现容器状态异常时,日志是唯一的真相("黑匣子")。
bash
# 查看最后 50 行日志(实时滚动)
docker logs -f --tail 50 <容器名或ID>
# 查看特定时间段的日志
docker logs --since "2023-10-27T10:00:00" <容器名>
3.3.1 容器名和 ID 从哪里来?
在使用 docker logs 之前,你需要知道目标容器的"身份证号"。
- 容器名 (NAMES) :
- 来源 :通常在启动容器时通过
--name参数手动指定。例如:docker run --name my-nginx -d nginx。 - 特点 :人类可读,方便记忆。如果你没指定,Docker 会自动生成一个随机的名字(如
happy_turing)。
- 来源 :通常在启动容器时通过
- 容器 ID (CONTAINER ID) :
- 来源 :Docker 自动生成的唯一标识符,一串十六进制字符(如
a1b2c3d4e5f6...)。 - 特点 :在命令行中,通常只需要输入前 3-4 位(短 ID)即可唯一识别,无需输入全称。
- 来源 :Docker 自动生成的唯一标识符,一串十六进制字符(如
3.3.2 怎么找到我要查的容器名或 ID?
如果你忘记了名字,可以通过以下命令查找:
bash
# 方法一:列出所有容器,人工查找
docker ps -a
# 方法二:模糊搜索(比如记得名字里带 "mysql")
docker ps -a | grep mysql
# 方法三:只获取 ID(适合配合其他命令使用)
docker ps -aq --filter "name=mysql"
# 方法四:查看某个容器的详细信息(包含完整的 ID、启动命令、挂载等)
docker inspect <容器名或ID>
实战技巧:
- 如果你想找跟 "mysql" 有关的容器:
docker ps -a | grep mysql - 如果你只想获取容器 ID(用于脚本):
docker ps -q - 如果你想看某个容器的完整信息(包括启动命令、环境变量、挂载目录等):
docker inspect <容器名>
3.3.3 常用日志查看命令
假设你要排查的容器名为 my-app(或者用 ID a1b2 代替):
bash
# 1. 基础查看:查看最后 100 行日志(最常用)
docker logs --tail 100 my-app
# 2. 实时跟踪:像看直播一样看日志输出(排查启动卡住时很有用)
docker logs -f my-app
# 按 Ctrl + C 退出实时模式
# 3. 带时间戳:查看日志发生的具体时间
docker logs -t --tail 50 my-app
# 4. 搜索错误:结合 grep 只看报错信息
docker logs my-app 2>&1 | grep -i "error"
# 5. 查看特定时间之后的日志
docker logs --since "2023-10-27T10:00:00" my-app
# 6. 查看特定时间之前的日志
docker logs --until "2023-10-27T12:00:00" my-app
# 7. 同时查看多个容器的日志
docker logs --tail 20 my-app1 && docker logs --tail 20 my-app2
技巧 :
2>&1的意思是将"标准错误输出"合并到"标准输出"中,防止有些程序的报错信息打印在另一条流里而被 grep 漏掉。
实战排查流程(四步法):
- 抓日志 :
docker logs --tail 100 <容器名> - 搜关键词 :
docker logs <容器名> 2>&1 | grep -iE "error|exception|panic|fatal" - 缩小时间范围 :如果故障发生在某个时间点,用
--since参数缩小范围 - 进入容器:如果日志看不出问题,进入容器内部检查
3.4 进入容器内部调试
有时候光看日志不够,需要进入容器内部检查配置文件、网络、文件等。
bash
# 进入容器的 bash 终端(容器需支持 bash)
docker exec -it <容器名> /bin/bash
# 进入容器的 sh 终端(轻量级,多数基础镜像支持)
docker exec -it <容器名> /bin/sh
# 在宿主机上执行容器内的命令(不需要进入容器)
docker exec <容器名> ps aux
docker exec <容器名> cat /etc/hostname
docker exec <容器名> env # 查看容器内的环境变量
参数拆解:
-i/--interactive:保持标准输入打开。-t/--tty:分配一个伪终端。exec:在运行中的容器内执行命令。
3.5 资源占用监控
当服务器变慢时,查看是哪个容器在"抢资源"。
bash
# 实时查看 CPU、内存、网络、IO 占用(类似 top 命令)
docker stats
# 查看某个容器的资源占用(一次性输出,不实时刷新)
docker stats <容器名> --no-stream
# 查看容器的详细资源限制
docker inspect <容器名> | grep -A 5 "Memory"
4. 常见问题处理(Troubleshooting)
4.1 容器处于 Restarting 状态
现象 :docker ps 显示 Restarting (1) 3 seconds ago。
原因 :容器启动命令执行失败,或者主进程崩溃,Docker 策略设为 always 导致无限重试。
解决步骤:
-
立即查看日志:
docker logs --tail 100 <容器ID> -
常见错误:配置文件路径错误、数据库连不上、端口被占用
-
如果确定要停止重启循环:
bashdocker update --restart=no <容器名> docker stop <容器名>
4.2 容器处于 Exited (137)
现象:容器意外退出,退出码 137。
原因 :OOM (Out Of Memory)。容器使用的内存超过了设定的 limit,被 Linux 内核杀掉了。
解决步骤:
- 验证:
docker inspect <容器ID> | grep -i oom(如果返回 true 则是内存溢出) - 查看系统内核日志确认:
dmesg | grep -i 'out of memory' | grep <容器名> - 调整:增加 Docker 内存限制或优化应用代码
4.3 容器处于 Created 状态
现象 :docker ps -a 显示 Created。
原因 :容器被创建了,但没有执行 docker start,或者启动命令(Entrypoint/Cmd)为空/错误。
解决步骤:
- 尝试启动:
docker start <容器名> - 检查配置:
docker inspect <容器名> | grep -A 5 "Cmd" - 如果启动后立刻变成
Exited,查看日志定位原因
4.4 容器内时间不对
现象:业务日志时间与北京时间差 8 小时。
原因:容器默认使用 UTC 时间,而宿主机是东八区。
解决:启动时挂载宿主机时间文件。
bash
docker run -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ...
4.5 磁盘空间满了(No space left on device)
现象:无法启动新容器,或者日志写不进去。
排查步骤:
bash
# 1. 查看磁盘整体使用率
df -h
# 2. 查看 Docker 占用了多少空间
docker system df
# 3. 一键清理(慎用!会删除所有停止的容器、未使用的网络和悬空镜像)
docker system prune
# 4. 安全清理(只删除未使用的镜像,保留容器)
docker image prune
# 5. 彻底清理(删除所有未使用的镜像、停止的容器、构建缓存)
docker system prune -a
# 6. 查找大日志文件(Docker 容器日志可能占用几十 G)
find /var/lib/docker/containers/ -name "*-json.log" -size +1G
# 7. 清空指定日志文件(不删除文件,只清空内容)
cat /dev/null > /var/lib/docker/containers/<长ID>/<长ID>-json.log
4.6 端口冲突
现象 :启动容器时报错 driver failed programming external connectivity。
原因:宿主机的端口已经被其他进程占用了。
解决步骤:
bash
# 1. 查看哪个进程占用了目标端口
netstat -tlnp | grep <端口号>
# 或
lsof -i :<端口号>
# 2. 杀掉占用端口的进程(谨慎操作)
kill -9 <PID>
# 3. 或者修改容器启动时的端口映射
docker run -p 新端口:容器端口 ...
4.7 容器无法联网
现象 :容器内 ping 或 curl 外网超时。
排查步骤:
bash
# 1. 检查 Docker 网络模式
docker inspect <容器名> | grep -A 5 "NetworkMode"
# 2. 进入容器检查 DNS 配置
docker exec <容器名> cat /etc/resolv.conf
# 3. 检查宿主机 DNS 是否正常
cat /etc/resolv.conf
# 4. 重启 Docker 网络(临时恢复)
sudo systemctl restart docker
5. Nacos 专项运维与排查实战
Nacos (Naming and Configuration Service) 是微服务架构的核心组件,承载了服务注册发现和配置管理两大功能。由于它一旦出问题往往是"爆炸性"的(所有微服务失联),因此需要特别关注其运行状态。
5.1 快速检查 Nacos 健康状态
不要只看 docker ps 显示 Up,Nacos 经常会出现"假死"状态(进程在,但无法响应 HTTP 请求)。
bash
# 1. 检查端口监听情况(默认端口 8848)
# 确保状态是 LISTEN,且不是 127.0.0.1(除非你只允许本机访问)
netstat -tlnp | grep 8848
# 2. 使用 curl 探测控制台接口(最准确)
# 如果返回 HTTP 200 或 HTML 内容,说明服务正常
curl -I http://<服务器IP>:8848/nacos/
# 3. 检查集群节点状态(如果是集群模式)
curl http://<服务器IP>:8848/nacos/v1/ns/operator/cluster/state
# 4. 查看服务注册列表(确认微服务是否注册成功)
curl http://<服务器IP>:8848/nacos/v1/cs/services?serviceName=<服务名>
5.2 Nacos 常见故障排查
场景一:Nacos 启动后自动退出 (Exited)
原因:Nacos 对内存非常敏感,默认 JVM 堆内存设置过大,超过了 Docker 容器的内存限制,导致被 OOM Killer 杀掉。
排查命令:
bash
# 查看退出码,如果是 137,大概率是内存溢出
docker inspect <容器ID> --format='{{.State.ExitCode}}'
# 查看系统内核日志确认 OOM
dmesg | grep -i 'out of memory' | grep nacos
解决方案:启动时通过环境变量调小 JVM 内存。
bash
# 示例:将堆内存限制为 512m
docker run -e JVM_XMS=256m -e JVM_XMX=512m ... nacos/nacos-server
场景二:微服务连不上 Nacos(注册失败)
原因:网络模式问题或 IP 漂移。Nacos 默认会注册服务器的内网 IP,如果 Docker 使用了桥接模式,微服务可能拿到的是错误的 IP。
排查命令:
bash
# 进入容器查看 Nacos 认为自己是谁
docker exec -it <nacos容器ID> cat /home/nacos/conf/application.properties
# 查看 Nacos 启动日志中的 IP 绑定信息
docker logs <nacos容器ID> | grep "Nacos started successfully"
# 查看 Nacos 启动完整日志
docker logs <nacos容器ID>
关键配置 :确保 nacos.inetutils.ip-address 配置的是微服务能访问到的真实 IP。
场景三:配置中心数据丢失或不更新
原因:数据库连接断开或 Derby 模式数据未持久化。
注意 :生产环境严禁使用默认的 Derby 嵌入式数据库,必须切换为 MySQL。
检查命令:
bash
# 检查是否连接到了外部 MySQL
docker logs <nacos容器ID> | grep "DataSource"
# 应该看到类似 HikariPool 初始化成功的日志,而不是 Derby
场景四:Nacos 控制台无法访问
排查步骤:
bash
# 1. 检查容器是否在运行
docker ps | grep nacos
# 2. 检查端口是否正确映射
docker inspect <nacos容器ID> | grep -A 10 "Ports"
# 3. 检查容器内部 Nacos 进程是否正常
docker exec -it <nacos容器ID> ps aux | grep nacos
# 4. 检查防火墙是否放行了 8848 端口
# CentOS/RHEL:
sudo firewall-cmd --list-ports | grep 8848
# Ubuntu/Debian:
sudo ufw status | grep 8848
# 5. 重启 Nacos 容器
docker restart nacos
5.3 Nacos 常用运维命令速查
| 操作 | 命令示例 | 说明 |
|---|---|---|
| 查看实时日志 | docker logs -f --tail 200 nacos |
关注 ERROR 和 WARN |
| 进入容器调试 | docker exec -it nacos bash |
Nacos 脚本通常在 /home/nacos/bin/ |
| 修改启动参数 | docker exec -it nacos vi /home/nacos/conf/application.properties |
修改后需重启容器生效 |
| 重启 Nacos | docker restart nacos |
配置修改后常用 |
| 查看 Nacos 版本 | docker exec nacos cat /home/nacos/version.txt |
确认当前版本 |
| 清理临时缓存 | rm -rf /home/nacos/data/protocol/raft |
高危操作:仅当集群元数据损坏导致无法选主时使用 |
5.4 Nacos 生产环境最佳实践 Checklist
- 持久化 :必须挂载
/home/nacos/data目录到宿主机,防止容器删除后配置丢失。 - 数据库:必须使用 MySQL 8.0/5.7 作为外部存储,严禁使用默认的 Derby。
- 单机模式 vs 集群 :
- 开发测试用单机模式(
MODE=standalone)。 - 生产环境务必使用集群模式(
MODE=cluster),至少 3 个节点。
- 开发测试用单机模式(
- 鉴权 :生产环境务必开启鉴权(
nacos.core.auth.enabled=true)并修改默认密钥,防止被黑客利用上传恶意配置。 - 内存限制 :通过
JVM_XMS和JVM_XMX环境变量合理设置堆内存,避免 OOM。 - 日志轮转:配置 Nacos 日志轮转策略,防止日志文件无限增长占满磁盘。
6. 附录:常用命令速查表
6.1 容器管理
| 操作 | 命令 | 说明 |
|---|---|---|
| 启动容器 | docker start <name> |
启动已停止的容器 |
| 停止容器 | docker stop <name> |
优雅停止(发送 SIGTERM) |
| 强制停止 | docker kill <name> |
立即杀掉进程(发送 SIGKILL) |
| 重启容器 | docker restart <name> |
先停止再启动 |
| 删除容器 | docker rm <name> |
需先停止,或加 -f 强制删除 |
| 创建容器(不启动) | docker create <镜像> |
仅创建,不运行 |
| 进入容器终端 | docker exec -it <name> /bin/bash |
交互式进入容器 |
| 复制文件到容器 | docker cp ./file.txt <name>:/path/ |
宿主机 -> 容器 |
| 复制文件出容器 | docker cp <name>:/path/file.txt ./ |
容器 -> 宿主机 |
6.2 镜像管理
| 操作 | 命令 | 说明 |
|---|---|---|
| 列出镜像 | docker images |
查看本地所有镜像 |
| 拉取镜像 | docker pull <镜像名> |
从仓库下载镜像 |
| 删除镜像 | docker rmi <镜像名> |
删除指定镜像 |
| 构建镜像 | docker build -t <名> . |
从 Dockerfile 构建 |
| 查看镜像详情 | docker inspect <镜像名> |
查看镜像配置信息 |
| 镜像打标签 | docker tag <旧名> <新名> |
给镜像重命名 |
| 推送镜像到仓库 | docker push <镜像名> |
上传到私有/公共仓库 |
6.3 网络与存储
| 操作 | 命令 | 说明 |
|---|---|---|
| 列出网络 | docker network ls |
查看 Docker 网络 |
| 创建网络 | docker network create <名> |
创建自定义网络 |
| 列出挂载卷 | docker volume ls |
查看持久化卷 |
| 创建卷 | docker volume create <名> |
创建命名卷 |
6.4 清理与监控
| 操作 | 命令 | 说明 |
|---|---|---|
| 实时资源监控 | docker stats |
类似 top,看 CPU/内存 |
| 查看系统信息 | docker info |
Docker 引擎详细信息 |
| 查看系统磁盘使用 | docker system df |
Docker 各组件占用空间 |
| 清理未使用的资源 | docker system prune |
删除停止容器、悬空镜像等 |
| 彻底清理 | docker system prune -a |
删除所有未使用的镜像 |
7. 附录:容器名与 ID 速查
很多新手在执行 docker logs、docker exec 等命令时,不知道 <容器名或ID> 该填什么。以下是快速查找的方法汇总:
bash
# 1. 列出所有容器,显示名字和 ID
docker ps -a
# 2. 只列出容器 ID(适合脚本中使用)
docker ps -q
# 3. 只列出容器 ID(包括已停止的)
docker ps -aq
# 4. 按名称模糊搜索容器
docker ps -a --filter "name=关键字"
# 5. 获取某个容器的完整 ID
docker inspect -f '{{.Id}}' <容器名>
# 6. 获取某个容器的短 ID(前 12 位)
docker inspect -f '{{.Id}}' <容器名> | cut -c1-12
命名规范建议:
- 容器名使用有意义的英文命名,如
myapp-backend、mysql-primary、nacos-cluster-1。 - 避免使用特殊字符和下划线以外的符号。
- 集群场景下用序号区分:
nacos-1、nacos-2、nacos-3。
8. 附录:Docker 常用启动参数速查
| 参数 | 说明 | 示例 |
|---|---|---|
-d |
后台运行(守护进程模式) | docker run -d nginx |
-p |
端口映射 | docker run -p 8080:80 nginx |
-v |
目录挂载(持久化数据) | docker run -v /data:/data nginx |
-e |
设置环境变量 | docker run -e MODE=standalone nacos |
--name |
指定容器名称 | docker run --name my-nginx nginx |
--restart |
重启策略 | --restart=always(总是重启) |
-it |
交互式终端 | docker run -it ubuntu /bin/bash |
--network |
指定网络 | docker run --network mynet nginx |
--memory |
内存限制 | docker run --memory 512m nginx |
--cpus |
CPU 限制 | docker run --cpus 1.5 nginx |
-h |
设置容器主机名 | docker run -h myhost nginx |
重启策略说明:
no:不自动重启(默认)。on-failure:容器非正常退出时才重启,可指定最大重启次数:on-failure:5。always:无论退出状态如何,总是重启。unless-stopped:同 always,但手动停止后不再重启。
核心原则 :先看状态(
docker ps),再看日志(docker logs),最后进容器调试(docker exec)。掌握这个顺序,你已经可以应对绝大多数 Docker 运维问题了。
