适用人群:Linux 运维新手、后端开发、DevOps 初学者

在这里插入图片描述


1. 核心概念:区分"Docker 服务"与"容器"

在开始之前,需要明确两个概念,避免混淆:

  • Docker 服务 (Daemon):指 Docker 引擎本身(dockerd)。如果它挂了,所有容器都会停止。
  • 容器 (Container):指运行在 Docker 里的具体应用(如 Nginx、MySQL、Nacos、你的业务代码)。

新手提示:通常我们说"查看 Docker 运行",既可能指查看引擎是否活着,也可能指查看里面的业务容器是否正常。下文将分开讲解。


2. 基础篇:查看 Docker 引擎状态

2.1 检查 Docker 引擎是否存活

这是最基础的命令,用于确认服务器上的 Docker 软件本身是否在运行。

# 查看详细的服务状态(推荐)
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 命令报错,可以用此命令验证。

docker info

输出解读:

  • 如果输出一大堆关于 Containers、Images、Storage Driver 的信息,说明连接正常。
  • 如果报错 Cannot connect to the Docker daemon,说明服务虽然启动了但 socket 文件有问题或权限不足。此时可尝试将当前用户加入 docker 用户组:sudo usermod -aG docker $USER,然后重新登录。

2.3 Docker 服务管理命令速查

操作命令说明
启动 Dockersudo systemctl start docker启动 Docker 引擎
停止 Dockersudo systemctl stop docker停止引擎(会停止所有容器)
重启 Dockersudo systemctl restart docker修改配置后常用
设置开机自启sudo systemctl enable docker防止服务器重启后服务丢失
查看 Docker 日志sudo journalctl -u docker.service排查引擎启动失败等问题

3. 进阶篇:查看与管理容器(业务服务)

这是日常工作中最高频的操作区域。

3.1 查看容器运行状态(黄金命令)

不要只用 docker ps,建议养成使用格式化输出的习惯,信息更直观。

# 查看所有容器(包括已退出的),并格式化输出
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}"

参数拆解:

  • -a / --all:显示所有容器,不仅仅是正在运行的。
  • --format:自定义输出列。这里我们按顺序展示:容器ID、名字、状态、镜像、端口映射。

输出示例与解读:

CONTAINER IDNAMESSTATUSIMAGEPORTS
a1b2c3d4e5f6nginx-webUp 2 hoursnginx:latest0.0.0.0:80->80/tcp
1854247741c4mysql-dbExited (1) 5 mins agomysql:8.03306/tcp
f9e8d7c6b5a4app-backendRestarting (1) 10s agomyapp:v1

状态关键字速查表:

状态关键字含义健康度
Up x hours正在运行中正常
Up x hours (healthy)正在运行且通过健康检查非常健康
Up x seconds刚启动不久需观察是否稳定
Exited (0)正常退出(任务完成或手动停止)视情况而定
Exited (1) / (137)异常退出(报错或被系统杀掉)异常
Restarting正在反复重启严重异常
Created已创建但未启动未运行
Paused已暂停需确认
Dead无法恢复异常

3.2 快速筛选特定状态的容器

当服务器上有几十个容器时,直接筛选更高效。

# 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 查看容器日志(排查神器)

当发现容器状态异常时,日志是唯一的真相(“黑匣子”)。

# 查看最后 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)即可唯一识别,无需输入全称。
3.3.2 怎么找到我要查的容器名或 ID?

如果你忘记了名字,可以通过以下命令查找:

# 方法一:列出所有容器,人工查找
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 代替):

# 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 漏掉。

实战排查流程(四步法):

  1. 抓日志docker logs --tail 100 <容器名>
  2. 搜关键词docker logs <容器名> 2>&1 | grep -iE "error|exception|panic|fatal"
  3. 缩小时间范围:如果故障发生在某个时间点,用 --since 参数缩小范围
  4. 进入容器:如果日志看不出问题,进入容器内部检查

3.4 进入容器内部调试

有时候光看日志不够,需要进入容器内部检查配置文件、网络、文件等。

# 进入容器的 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 资源占用监控

当服务器变慢时,查看是哪个容器在"抢资源"。

# 实时查看 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 导致无限重试。

解决步骤:

  1. 立即查看日志:docker logs --tail 100 <容器ID>
  2. 常见错误:配置文件路径错误、数据库连不上、端口被占用
  3. 如果确定要停止重启循环:
    docker update --restart=no <容器名>
    docker stop <容器名>
    

4.2 容器处于 Exited (137)

现象:容器意外退出,退出码 137。

原因OOM (Out Of Memory)。容器使用的内存超过了设定的 limit,被 Linux 内核杀掉了。

解决步骤:

  1. 验证:docker inspect <容器ID> | grep -i oom(如果返回 true 则是内存溢出)
  2. 查看系统内核日志确认:dmesg | grep -i 'out of memory' | grep <容器名>
  3. 调整:增加 Docker 内存限制或优化应用代码

4.3 容器处于 Created 状态

现象docker ps -a 显示 Created

原因:容器被创建了,但没有执行 docker start,或者启动命令(Entrypoint/Cmd)为空/错误。

解决步骤:

  1. 尝试启动:docker start <容器名>
  2. 检查配置:docker inspect <容器名> | grep -A 5 "Cmd"
  3. 如果启动后立刻变成 Exited,查看日志定位原因

4.4 容器内时间不对

现象:业务日志时间与北京时间差 8 小时。

原因:容器默认使用 UTC 时间,而宿主机是东八区。

解决:启动时挂载宿主机时间文件。

docker run -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ...

4.5 磁盘空间满了(No space left on device)

现象:无法启动新容器,或者日志写不进去。

排查步骤:

# 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

原因:宿主机的端口已经被其他进程占用了。

解决步骤:

# 1. 查看哪个进程占用了目标端口
netstat -tlnp | grep <端口号>
# 或
lsof -i :<端口号>

# 2. 杀掉占用端口的进程(谨慎操作)
kill -9 <PID>

# 3. 或者修改容器启动时的端口映射
docker run -p 新端口:容器端口 ...

4.7 容器无法联网

现象:容器内 pingcurl 外网超时。

排查步骤:

# 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 请求)。

# 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 杀掉。

排查命令

# 查看退出码,如果是 137,大概率是内存溢出
docker inspect <容器ID> --format='{{.State.ExitCode}}'

# 查看系统内核日志确认 OOM
dmesg | grep -i 'out of memory' | grep nacos

解决方案:启动时通过环境变量调小 JVM 内存。

# 示例:将堆内存限制为 512m
docker run -e JVM_XMS=256m -e JVM_XMX=512m ... nacos/nacos-server
场景二:微服务连不上 Nacos(注册失败)

原因:网络模式问题或 IP 漂移。Nacos 默认会注册服务器的内网 IP,如果 Docker 使用了桥接模式,微服务可能拿到的是错误的 IP。

排查命令

# 进入容器查看 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。

检查命令

# 检查是否连接到了外部 MySQL
docker logs <nacos容器ID> | grep "DataSource"
# 应该看到类似 HikariPool 初始化成功的日志,而不是 Derby
场景四:Nacos 控制台无法访问

排查步骤

# 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 bashNacos 脚本通常在 /home/nacos/bin/
修改启动参数docker exec -it nacos vi /home/nacos/conf/application.properties修改后需重启容器生效
重启 Nacosdocker restart nacos配置修改后常用
查看 Nacos 版本docker exec nacos cat /home/nacos/version.txt确认当前版本
清理临时缓存rm -rf /home/nacos/data/protocol/raft高危操作:仅当集群元数据损坏导致无法选主时使用

5.4 Nacos 生产环境最佳实践 Checklist

  1. 持久化:必须挂载 /home/nacos/data 目录到宿主机,防止容器删除后配置丢失。
  2. 数据库:必须使用 MySQL 8.0/5.7 作为外部存储,严禁使用默认的 Derby。
  3. 单机模式 vs 集群
    • 开发测试用单机模式(MODE=standalone)。
    • 生产环境务必使用集群模式(MODE=cluster),至少 3 个节点。
  4. 鉴权:生产环境务必开启鉴权(nacos.core.auth.enabled=true)并修改默认密钥,防止被黑客利用上传恶意配置。
  5. 内存限制:通过 JVM_XMSJVM_XMX 环境变量合理设置堆内存,避免 OOM。
  6. 日志轮转:配置 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 infoDocker 引擎详细信息
查看系统磁盘使用docker system dfDocker 各组件占用空间
清理未使用的资源docker system prune删除停止容器、悬空镜像等
彻底清理docker system prune -a删除所有未使用的镜像

7. 附录:容器名与 ID 速查

很多新手在执行 docker logsdocker exec 等命令时,不知道 <容器名或ID> 该填什么。以下是快速查找的方法汇总:

# 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-backendmysql-primarynacos-cluster-1
  • 避免使用特殊字符和下划线以外的符号。
  • 集群场景下用序号区分:nacos-1nacos-2nacos-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
--cpusCPU 限制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 运维问题了。

更多推荐