目录

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 CMDENTRYPOINT 和参数覆盖

镜像可以定义:

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 renamedocker waitdocker diff

docker rename old-name new-name

重命名不影响容器运行状态。在自动化脚本中,如果先 createrename,要确保后续操作使用新名字。

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/amd64linux/arm64linux/arm/v7

在 Docker Desktop 上可以通过 QEMU 运行非本机架构的容器,但性能明显低于原生架构,不要用于性能基准测试。

8. 重启策略、资源管理与 docker update

这两个主题内容较多,已拆为独立文章:

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 只显示运行中的容器;排查“容器启动后消失”时一定要加 -ainspect 是结构化 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 inspectdocker 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.ExitCodeState.OOMKilledState.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 inspectOOMKilled、应用日志、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/importsave/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 -fdocker 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-重启策略与健康检查