Docker 完全指南 / 05 - 容器管理
05 - 容器管理
掌握容器的完整生命周期:创建、运行、停止、删除,以及 exec、logs、inspect 等调试技巧。
5.1 容器生命周期
容器状态流转:
┌─────────┐ docker create ┌──────────┐ docker start ┌───────────┐
│ Image │ ──────────────> │ Created │ ──────────────> │ Running │
└─────────┘ └──────────┘ └─────┬─────┘
│
┌──────────────┐ docker stop │
│ Stopped │ <─────────────────────┤
└──────┬───────┘ │
│ │
docker restart │
│ docker pause │
▼ ───────────> ┌──────────┐
┌───────────┐ │ Paused │
│ Running │ <── docker unpause └──────────┘
└─────┬─────┘
│
docker kill / 进程退出
│
▼
┌──────────┐ docker rm ┌─────────┐
│ Exited │ ──────────> │ Removed │
└──────────┘ └─────────┘
状态说明
| 状态 | 说明 | 典型操作 |
|---|---|---|
| Created | 已创建但未启动 | docker create |
| Running | 运行中 | docker start, docker run |
| Paused | 已暂停(进程冻结) | docker pause |
| Exited | 已退出(进程结束) | docker stop, docker kill |
| Removing | 正在删除中 | docker rm |
| Dead | 异常状态 | 需手动清理 |
5.2 创建容器(Create)
docker create 创建容器但不启动:
# 创建容器
docker create --name my-nginx -p 8080:80 nginx:alpine
# 查看已创建的容器
docker ps -a
# 稍后启动
docker start my-nginx
5.3 运行容器(Run)
docker run 是最常用的命令,等价于 create + start。
基本语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
常用选项详解
| 选项 | 缩写 | 说明 | 示例 |
|---|---|---|---|
--name | 容器名称 | --name web | |
--detach | -d | 后台运行 | -d |
--interactive | -i | 保持标准输入打开 | -i |
--tty | -t | 分配伪终端 | -t |
--rm | 退出后自动删除 | --rm | |
--publish | -p | 端口映射 | -p 8080:80 |
--volume | -v | 挂载卷 | -v data:/app |
--env | -e | 设置环境变量 | -e NODE_ENV=prod |
--network | 指定网络 | --network mynet | |
--restart | 重启策略 | --restart unless-stopped | |
--memory | -m | 内存限制 | -m 512m |
--cpus | CPU 限制 | --cpus 1.5 | |
--workdir | -w | 工作目录 | -w /app |
--user | -u | 指定用户 | -u 1000:1000 |
--entrypoint | 覆盖入口点 | --entrypoint /bin/sh |
常见运行模式
# 1. 后台运行服务
docker run -d --name nginx-web -p 8080:80 nginx:alpine
# 2. 交互式 shell
docker run -it --name dev-ubuntu ubuntu:22.04 bash
# 3. 一次性任务(运行后自动删除)
docker run --rm ubuntu:22.04 echo "Hello Docker"
# 4. 带资源限制的运行
docker run -d --name limited \
-m 256m --cpus 0.5 \
-p 8080:80 nginx:alpine
# 5. 挂载数据卷的运行
docker run -d --name data-nginx \
-v ./html:/usr/share/nginx/html:ro \
-p 8080:80 nginx:alpine
# 6. 设置环境变量
docker run -d --name db \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=myapp \
-p 5432:5432 postgres:16
# 7. 设置重启策略
docker run -d --restart unless-stopped \
--name always-nginx -p 8080:80 nginx:alpine
# 8. 使用主机网络
docker run -d --network host nginx:alpine
# 9. 覆盖入口点
docker run -it --entrypoint /bin/sh nginx:alpine
# 10. 添加额外的 hosts 记录
docker run -d --add-host host.docker.internal:host-gateway nginx:alpine
重启策略
| 策略 | 说明 |
|---|---|
no | 默认,不自动重启 |
on-failure[:max] | 非零退出码时重启,可指定最大次数 |
always | 总是重启(包括 daemon 启动时) |
unless-stopped | 总是重启,除非手动停止 |
# 设置重启策略
docker run -d --restart on-failure:5 --name web nginx:alpine
# 查看重启次数
docker inspect --format '{{.RestartCount}}' web
# 修改已有容器的重启策略
docker update --restart unless-stopped web
5.4 容器列表(PS)
# 运行中的容器
docker ps
# 所有容器(包括已停止的)
docker ps -a
# 仅显示容器 ID
docker ps -q
# 格式化输出
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"
# 自定义格式
docker ps --format '{"id":"{{.ID}}","name":"{{.Names}}","status":"{{.Status}}"}'
# 过滤
docker ps --filter "status=running"
docker ps --filter "name=web"
docker ps --filter "ancestor=nginx:alpine"
docker ps --filter "label=env=production"
# 按大小排序
docker ps -s --format "table {{.Names}}\t{{.Size}}"
# 最近创建的 N 个容器
docker ps -n 5
5.5 容器日志(Logs)
# 查看全部日志
docker logs my-container
# 实时跟踪日志(类似 tail -f)
docker logs -f my-container
# 显示最近 N 行
docker logs --tail 100 my-container
# 显示时间戳
docker logs -t my-container
# 查看指定时间后的日志
docker logs --since 2024-01-01T00:00:00 my-container
docker logs --since 30m my-container # 最近 30 分钟
# 查看指定时间前的日志
docker logs --until 2024-01-02T00:00:00 my-container
# 组合使用
docker logs -f --tail 50 --since 10m my-container
日志驱动
| 驱动 | 说明 | 用途 |
|---|---|---|
json-file | 默认,JSON 格式写入文件 | 通用 |
syslog | 发送到 syslog | 集中日志 |
journald | 发送到 systemd journal | systemd 环境 |
fluentd | 发送到 fluentd | 日志聚合 |
awslogs | 发送到 AWS CloudWatch | AWS 环境 |
none | 禁用日志 | 无需日志的场景 |
# 查看当前日志驱动
docker info | grep "Logging Driver"
# 为单个容器指定日志驱动
docker run -d \
--log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
--name web nginx:alpine
# 全局配置 (/etc/docker/daemon.json)
# {
# "log-driver": "json-file",
# "log-opts": {
# "max-size": "10m",
# "max-file": "3"
# }
# }
5.6 进入容器(Exec)
# 进入运行中的容器(交互式 shell)
docker exec -it my-container /bin/bash
# 如果容器没有 bash,使用 sh
docker exec -it my-container /bin/sh
# 以 root 用户进入
docker exec -it -u root my-container /bin/bash
# 执行单条命令(不进入交互模式)
docker exec my-container cat /etc/os-release
docker exec my-container ls -la /app
docker exec my-container env
# 设置环境变量
docker exec -e MY_VAR=hello my-container printenv MY_VAR
# 在指定目录执行
docker exec -w /tmp my-container pwd
# 以指定用户执行
docker exec -u www-data my-container whoami
exec vs attach
| 特性 | docker exec | docker attach |
|---|---|---|
| 创建新进程 | ✅ 新进程 | ❌ 连接主进程 |
| 退出影响 | 不影响容器 | 可能停止容器 |
| 多终端 | ✅ 多个 exec | ❌ 只能一个 attach |
| 用途 | 调试、运行命令 | 查看主进程输出 |
# attach 到容器主进程
docker attach my-container
# 退出: Ctrl+P, Ctrl+Q(detach)
# 注意: 不要按 Ctrl+C,会终止容器主进程
5.7 容器信息(Inspect)
# 查看完整 JSON 信息
docker inspect my-container
# 使用 Go template 提取特定字段
docker inspect --format '{{.State.Status}}' my-container
docker inspect --format '{{.NetworkSettings.IPAddress}}' my-container
docker inspect --format '{{.HostConfig.Memory}}' my-container
docker inspect --format '{{json .State}}' my-container
# 使用 jq 过滤(更灵活)
docker inspect my-container | jq '.[0].State'
docker inspect my-container | jq '.[0].NetworkSettings.Networks'
docker inspect my-container | jq '.[0].Mounts'
docker inspect my-container | jq '.[0].Config.Env'
常用 inspect 字段
| 字段路径 | 说明 |
|---|---|
.State.Status | 容器状态 |
.State.Pid | 主进程 PID |
.State.StartedAt | 启动时间 |
.NetworkSettings.IPAddress | 容器 IP |
.NetworkSettings.Ports | 端口映射 |
.HostConfig.Memory | 内存限制 |
.HostConfig.NanoCpus | CPU 限制 |
.Mounts | 挂载信息 |
.Config.Image | 使用的镜像 |
.Config.Env | 环境变量 |
5.8 容器的文件操作
# 从宿主机复制到容器
docker cp ./config.yml my-container:/app/config.yml
# 从容器复制到宿主机
docker cp my-container:/var/log/nginx/access.log ./access.log
# 复制目录
docker cp ./templates my-container:/app/templates
5.9 容器资源监控
# 实时查看容器资源使用
docker stats
# 仅查看一次(不持续更新)
docker stats --no-stream
# 指定容器
docker stats my-container --no-stream
# 格式化输出
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
# 输出示例:
# NAME CPU % MEM USAGE / LIMIT NET I/O BLOCK I/O
# web 0.15% 15MiB / 256MiB 1.2kB / 0B 0B / 0B
# db 1.25% 120MiB / 512MiB 5.6kB / 2.1kB 12MB / 0B
5.10 容器停止与删除
# 停止容器(发送 SIGTERM,超时后 SIGKILL)
docker stop my-container
# 指定超时时间(默认 10 秒)
docker stop -t 30 my-container
# 强制停止(直接 SIGKILL)
docker kill my-container
# 发送指定信号
docker kill --signal=SIGHUP my-container
# 重启容器
docker restart my-container
# 暂停/恢复容器
docker pause my-container
docker unpause my-container
# 删除已停止的容器
docker rm my-container
# 强制删除运行中的容器
docker rm -f my-container
# 删除所有已停止的容器
docker container prune
# 删除所有已停止的容器(跳过确认)
docker container prune -f
# 删除指定时间前的已停止容器
docker container prune --filter "until=24h"
批量操作
# 停止所有运行中的容器
docker stop $(docker ps -q)
# 删除所有已停止的容器
docker rm $(docker ps -aq --filter "status=exited")
# 删除所有容器(危险!)
docker rm -f $(docker ps -aq)
5.11 等待与事件监听
# 等待容器停止并获取退出码
docker wait my-container
# 输出: 0 (正常退出)
# 查看容器的退出码
docker inspect --format '{{.State.ExitCode}}' my-container
# 查看容器的 OOM(内存溢出)状态
docker inspect --format '{{.State.OOMKilled}}' my-container
# 实时监听 Docker 事件
docker events
# 过滤特定类型的事件
docker events --filter "type=container"
docker events --filter "event=start"
docker events --filter "container=my-container"
# 查看最近 5 分钟的事件
docker events --since 5m
# JSON 格式输出
docker events --format '{{json .}}'
5.12 容器重命名与更新
# 重命名容器
docker rename old-name new-name
# 更新容器配置(运行中的容器)
docker update --restart unless-stopped my-container
docker update --memory 512m --cpus 1 my-container
要点回顾
| 要点 | 核心内容 |
|---|---|
| run 命令 | 最常用,-d 后台运行,-it 交互式,--rm 自动清理 |
| 日志管理 | docker logs -f --tail,注意配置日志轮转 |
| exec 调试 | 进入容器调试首选方式,不影响主进程 |
| 资源限制 | --memory, --cpus 限制资源使用 |
| 重启策略 | 生产环境使用 unless-stopped |
| 清理 | 定期 docker system prune 清理无用资源 |
注意事项
容器内 PID 1: 容器内的第一个进程是 PID 1,它负责处理信号和回收子进程。使用
exec模式(而非 shell 模式)确保应用成为 PID 1。
日志轮转: 默认不限制日志大小,可能导致磁盘写满。务必在 daemon.json 中配置
max-size和max-file。
优雅停止: Docker 默认等待 10 秒后才强制停止容器。如果应用需要更长的关闭时间,使用
docker stop -t 60或在 Dockerfile 中设置STOPSIGNAL。
下一步
→ 06 - Dockerfile 详解:学习如何编写高效的 Dockerfile。