Docker-03 镜像、容器与常用命令:把生命周期跑通
快速跳转: 镜像命令 · docker run · 容器生命周期 · create vs run · pause/unpause · rename/wait/diff · 多架构拉取 · 查看状态 · docker inspect · 调试容器 · 日志与退出码 · 清理策略 · 排障流程
1. 镜像命令
1.1 搜索、拉取和查看
docker search nginx
docker pull nginx:1.27-alpine
docker images
docker image ls --digests
docker image inspect nginx:1.27-alpine
docker pull 下载 manifest 和缺失的 layer。docker image inspect 查看的是本地镜像元数据,包括 entrypoint、默认命令、环境变量、工作目录、架构和 rootfs layer。
生产环境建议记录 digest:
docker image inspect nginx:1.27-alpine \
--format '{{index .RepoDigests 0}}'
注意:一个 tag 可能随时间变化;RepoDigests 只有在从支持 digest 的 registry 拉取或推送后才一定存在。
1.2 删除镜像
docker image rm nginx:1.27-alpine
docker image prune # 删除悬空镜像
docker image prune -a # 删除未被容器使用的镜像,先确认
如果镜像仍被容器(包括已停止的容器)引用,删除会失败。先查看:
docker ps -a --filter ancestor=nginx:1.27-alpine
2. docker run 的重要参数
docker run -d \
--name web \
--restart unless-stopped \
-p 127.0.0.1:8080:80 \
-e APP_ENV=dev \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
nginx:1.27-alpine
常见参数:
| 参数 | 作用 |
|---|---|
-d |
后台运行,返回容器 ID |
--name |
指定可读容器名 |
--rm |
容器退出后自动删除,适合一次性任务 |
-it |
连接交互终端,通常等价于 -i -t |
-p host:container |
发布端口,可指定监听地址 |
-P |
发布所有 EXPOSE 端口到随机宿主端口 |
-e / --env-file |
设置环境变量 |
-v / --mount |
挂载 volume、bind 或 tmpfs |
--network |
加入指定网络 |
--hostname |
设置容器 hostname |
--restart |
设置退出后的重启策略 |
--cpus / --memory |
限制 CPU 和内存 |
--user |
指定容器内 UID/GID |
--read-only |
将容器根文件系统设为只读 |
--init |
注入轻量 init,处理信号和孤儿进程 |
--cap-drop / --security-opt |
限制 capability、seccomp 等安全能力 |
2.1 CMD、ENTRYPOINT 和参数覆盖
镜像可以定义:
ENTRYPOINT ["/usr/local/bin/server"]
CMD ["--config", "/etc/server/config.yaml"]
运行时:
docker run image # server --config /etc/server/config.yaml
docker run image --port 8080 # server --port 8080
docker run --entrypoint /bin/sh image # 完全替换 ENTRYPOINT
JSON 数组形式是 exec form,进程会直接成为 PID 1,更适合正确接收 SIGTERM。ENTRYPOINT 写成 shell form 时,shell 可能截留信号。
3. 容器生命周期
create → start → running → stop → exited
↘ restart
↘ kill
exited → start
任何状态 → rm(删除容器元数据和可写层)
对应命令:
docker create --name web nginx:alpine
docker start web
docker stop -t 10 web
docker restart web
docker kill web
docker pause web
docker unpause web
docker rm web
docker rm -f web
stop 先发送 SIGTERM,等待超时后发送 SIGKILL;kill 默认直接发送 SIGKILL。生产应用应实现优雅退出,不要习惯性使用 rm -f 掩盖问题。
4. docker create vs docker run
docker run = docker create + docker start。需要在启动前做额外操作时,可以分两步:
docker create --name web -p 127.0.0.1:8080:80 nginx:alpine
docker cp ./nginx.conf web:/etc/nginx/nginx.conf
docker start web
create 后容器处于 Created 状态,可写层已分配,但进程未启动。
5. docker pause / unpause:冻结和恢复容器
docker pause web
docker inspect -f '{{.State.Status}}' web # paused
docker unpause web
pause 使用 cgroup freezer 挂起容器内所有进程,不发送信号,进程不感知被冻结。适合短暂冻结以做快照或调试,不要用于长期停机——stop 才是正确的方式。
6. docker rename、docker wait 和 docker diff
docker rename old-name new-name
重命名不影响容器运行状态。在自动化脚本中,如果先 create 再 rename,要确保后续操作使用新名字。
docker wait job-container
echo $?
docker wait 阻塞直到容器退出,返回退出码。适合脚本中等待一次性任务完成:
docker run -d --name migration example/api:1.0.0 /app/migrate
exit_code=$(docker wait migration)
if [ “$exit_code” -ne 0 ]; then
echo “migration failed with code $exit_code”
docker logs migration
exit 1
fi
docker rm migration
docker diff web
docker diff 显示容器文件系统相对于镜像的变更:A(Added)、C(Changed)、D(Deleted)。排查”容器内哪些文件被修改了”时很有用。
7. 多架构拉取:--platform
docker pull --platform linux/arm64 nginx:alpine
docker image inspect nginx:alpine --format '{{.Os}}/{{.Architecture}}'
默认拉取与宿主机架构匹配的镜像。交叉测试或为其他架构构建时,用 --platform 指定。常见值:linux/amd64、linux/arm64、linux/arm/v7。
在 Docker Desktop 上可以通过 QEMU 运行非本机架构的容器,但性能明显低于原生架构,不要用于性能基准测试。
8. 重启策略、资源管理与 docker update
这两个主题内容较多,已拆为独立文章:
- Docker-04 重启策略与健康检查 — 四种 restart policy 的行为边界、Compose restart 语义、健康检查参数调优、depends_on 启动顺序、信号传递与优雅退出
- Docker-05 资源管理与 docker update — 动态调整 CPU/内存/PIDs/IO、cgroup v2 映射、容器内 CPU 和内存视图不准确的原因、docker stats 详解
9. 查看容器状态和文件变更
docker ps
docker ps -a
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker inspect web
docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.OOMKilled}}' web
docker top web
docker stats --no-stream web
docker ps 只显示运行中的容器;排查“容器启动后消失”时一定要加 -a。inspect 是结构化 JSON,遇到复杂嵌套字段时配合 Go template 或 jq:
docker inspect web | jq '.[0] | {
state: .State.Status,
pid: .State.Pid,
mounts: .Mounts,
networks: .NetworkSettings.Networks
}'
docker diff 也可以在这个阶段使用,快速查看容器的文件系统相对于镜像发生了哪些变化:
docker diff web
输出中 A = 新增文件、C = 修改文件、D = 删除文件。排查"容器内被意外修改了什么"时非常有用。
10. docker inspect 深入:读懂容器和镜像的全部元数据
docker inspect 返回一个 JSON 数组,包含对象的完整配置和状态。它是排障和自动化的核心工具。
10.1 容器 inspect vs 镜像 inspect
docker inspect web # 自动判断类型
docker container inspect web # 显式指定容器
docker image inspect nginx:alpine # 显式指定镜像
当容器和镜像同名时,docker inspect 优先匹配容器。生产脚本应使用 docker container inspect 或 docker image inspect 避免歧义。
10.2 容器 inspect 的关键字段
.[0]
├── .State — 运行状态、PID、退出码、OOMKilled、启动/结束时间
├── .Config — 镜像定义:Env、Cmd、Entrypoint、Labels、ExposedPorts
├── .HostConfig — 运行时配置:RestartPolicy、Memory、NanoCpus、Binds、PortBindings
├── .NetworkSettings— 网络:IP、Gateway、Ports、Networks(每个网络的地址)
├── .Mounts — 挂载列表:Type、Source、Destination、RW
└── .GraphDriver — 存储驱动和层目录
10.3 Go template 常用模式
单字段提取:
docker inspect -f '{{.State.Pid}}' web
docker inspect -f '{{.State.Status}}' web
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' web
docker inspect -f '{{.NetworkSettings.IPAddress}}' web
多字段组合:
docker inspect -f 'status={{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}}' web
遍历列表(例如挂载点):
docker inspect -f '{{range .Mounts}}{{.Type}} {{.Source}} → {{.Destination}} (rw={{.RW}}){{"\n"}}{{end}}' web
获取特定网络的 IP:
docker inspect -f '{{(index .NetworkSettings.Networks "app").IPAddress}}' web
输出 JSON 子树(配合 jq 更灵活):
docker inspect -f '{{json .NetworkSettings.Ports}}' web | jq .
10.4 镜像 inspect 的关键字段
docker image inspect nginx:alpine --format '{{.Os}}/{{.Architecture}}'
docker image inspect nginx:alpine --format '{{.Config.Entrypoint}} {{.Config.Cmd}}'
docker image inspect nginx:alpine --format '{{index .RepoDigests 0}}'
docker image inspect nginx:alpine --format '{{json .RootFS.Layers}}' | jq 'length'
RootFS.Layers 是镜像的 diff ID 列表,可以用来判断两个镜像共享了多少层。
10.5 配合 jq 做复杂查询
docker inspect web | jq '.[0].NetworkSettings.Networks | to_entries[] | {network: .key, ip: .value.IPAddress}'
批量查询所有运行中容器的名称和 IP:
docker ps -q | xargs docker inspect | jq '.[] | {name: .Name, ip: .NetworkSettings.IPAddress}'
查看容器的环境变量(排查配置问题):
docker inspect web | jq '.[0].Config.Env[]' -r
10.6 使用场景和注意事项
- 排障:
State.ExitCode、State.OOMKilled、State.Error是第一手证据 - 自动化:CI/CD 脚本用
--format提取端口、IP、状态做条件判断 - 审计:inspect 输出保存为 JSON 文件,作为变更前后的对比基线
inspect显示的是 Docker daemon 记录的元数据,不等于容器内进程的实时状态;进程可能已经卡死但 State 仍然显示 running- 不要用
inspect的输出作为安全凭据来源(环境变量可能包含密码,inspect 会完整显示)
11. 进入和调试容器
docker exec -it web sh
docker exec web env
docker exec web ps -ef
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./healthcheck.sh web:/tmp/healthcheck.sh
docker exec 启动的是容器内的另一个进程,不是“登录到容器”。如果主进程已经退出,不能使用 exec;可以先查看日志,或用相同镜像启动一个临时 shell:
docker run --rm -it --entrypoint sh nginx:alpine
调试生产容器时尽量不要直接安装软件改动容器,因为这些修改不会进入镜像且无法复现。应该修复 Dockerfile 后重新构建。
12. 日志和退出码
docker logs web
docker logs -f --tail 200 web
docker logs --since 10m --timestamps web
docker events --since 10m
容器日志默认来自 stdout/stderr,而不是任意写入的文件。退出码常见含义:
| 退出码 | 常见含义 |
|---|---|
0 |
程序正常结束,一次性任务常见 |
1 |
应用一般错误 |
126 |
找到命令但无法执行,可能无执行权限 |
127 |
找不到命令 |
137 |
128 + SIGKILL,常见于 OOM 或被强制 kill |
139 |
128 + SIGSEGV,段错误 |
143 |
128 + SIGTERM,通常是正常停止路径 |
退出码不是根因。要结合 docker inspect 的 OOMKilled、应用日志、daemon 日志和宿主机内核日志判断。
13. 复制、导入和导出
# 将容器文件系统导出为 tar(不包含镜像历史和 volume)
docker export web -o web-rootfs.tar
# 将 tar 导入为一个扁平镜像
docker import web-rootfs.tar local/web:debug
# 保存/加载镜像,保留镜像层和元数据
docker save nginx:alpine -o nginx.tar
docker load -i nginx.tar
export/import 和 save/load 解决的问题不同:前者面向容器 rootfs,后者面向镜像分层。不要用 docker export 备份数据库 volume。
14. 清理策略
先观察空间:
docker system df
docker system df -v
按风险从低到高清理:
docker container prune # 已停止容器
docker image prune # 悬空镜像
docker builder prune # BuildKit 缓存
docker network prune # 未使用网络
docker volume prune # 未使用卷,数据风险最高
docker system prune 会组合清理多个对象;加 -a、--volumes 后影响更大。生产机应先列出目标、确认备份和业务窗口,再执行。
15. 一套通用排障流程
容器是否存在? docker ps -a
容器为何退出? docker inspect + docker logs
进程是否被 OOM? State.OOMKilled + docker stats + dmesg
端口是否监听? docker port + ss -lntp
网络是否连通? docker inspect network + getent/curl
挂载是否正确? docker inspect .Mounts + 容器内 df/ls
镜像是否匹配架构? docker image inspect .Architecture
daemon 是否异常? journalctl -u docker
不要一上来执行 docker rm -f、docker system prune -a,它们会破坏现场。先保存 inspect、日志和 docker events。
16. 高频命令速查
# 镜像
docker pull IMAGE
docker build -t NAME:TAG .
docker image ls
docker image inspect IMAGE
docker image rm IMAGE
# 容器
docker run --name NAME IMAGE
docker create --name NAME IMAGE
docker ps -a
docker start/stop/restart NAME
docker pause/unpause NAME
docker rename OLD NEW
docker wait NAME
docker diff NAME
docker exec -it NAME sh
docker inspect NAME
docker logs -f NAME
docker stats NAME
docker rm NAME
# 系统
docker info
docker system df
docker system prune
docker context ls
docker events
17. 本篇小结
命令的关键不是记住每个短参数,而是知道它操作哪个对象:镜像是不可变构建产物,容器是运行实例,volume 承载持久数据,network 决定连通性,daemon 负责统一管理。排障时保留现场,优先使用 inspect、日志和事件获得证据。
| 上一篇 | 下一篇 |
|---|---|
| 02-安装与配置 | 04-重启策略与健康检查 |