Skip to content

Docker 命令从对象模型到生产操作

Docker 命令不是一组需要死记的缩写。每条命令都在读取或改变某个对象:context、image、container、network、volume、builder 或 Compose project。真正需要掌握的是命令的输入对象、产生的状态变化、数据是否保留、输出如何判读,以及命令失败后应该查哪一层。

本页以“对象 → 生命周期 → 只读检查 → 状态变更 → 风险边界”组织命令。容器字段的深入判读见 Docker容器信息与生产诊断,事故决策流程见 Docker生产故障排查Runbook

学习目标

学完后,应能:

  1. 看懂 docker [管理对象] [动作] [选项] [对象] 的命令结构。
  2. 区分 image、container、network、volume、context、builder 和 Compose project。
  3. 正确解释 create、start、run、stop、kill、restart、rm 的状态变化。
  4. 正确使用 pull、tag、push、save/load,并区分 export/import。
  5. 使用 filter、format、inspect 和 label 精确定位对象,而不是复制 ID 后盲目操作。
  6. 使用 logs、stats、top、exec、cp、events 完成运行中和已退出容器诊断。
  7. 创建网络和 Volume,理解删除容器、镜像和卷对数据的不同影响。
  8. 执行删除与清理前证明目标对象、引用关系、业务归属和恢复能力。
  9. 完成一个从拉镜像、运行、验证、修改、停止到安全清理的可重复实验。

一、先读懂Docker CLI命令结构

现代 Docker CLI 常见结构:

text
docker <management-command> <subcommand> [OPTIONS] [ARGUMENTS]

例如:

bash
docker container ls --all
docker image inspect nginx:1.27
docker network create demo-net
docker volume inspect demo-data

也有兼容的短写:

bash
docker ps -a
docker images
docker inspect nginx:1.27

建议初学时先理解完整对象形式,再使用熟悉的短写:

完整形式常见短写对象
docker container lsdocker psContainer
docker image lsdocker imagesImage
docker container rmdocker rmContainer
docker image rmdocker rmiImage

1.1 命令帮助是第一手边界说明

bash
docker --help
docker container --help
docker run --help
docker inspect --help

不同 Docker/Compose 版本支持的选项可能不同。遇到教程参数不可用,先执行:

bash
docker version
docker compose version
docker <> --help

不要先假定安装损坏。

1.2 选项位置为什么重要

Docker CLI 全局选项和子命令选项作用域不同:

bash
docker --context prod container ls

这里 --context 作用于 Docker CLI 连接目标。

bash
docker container ls --all

这里 --all 作用于 container ls。

运行容器时,镜像名前是 Docker 的 run 参数,镜像名后的内容通常是传给容器的命令或参数:

bash
docker run --name demo nginx:1.27 nginx -T

拆解:

text
docker run                 Docker动作
--name demo                run选项
nginx:1.27                 镜像
nginx -T                   覆盖或传给容器的命令参数

-p-e 放到镜像名后面,可能不再被 Docker 当作 run 选项,而是传给镜像入口程序。

二、Docker对象关系与数据生命周期

mermaid
flowchart TD
    A["Registry远程镜像仓库"] --> B["docker pull"]
    B --> C["Image本地只读镜像"]
    D["Dockerfile与构建上下文"] --> E["docker build"]
    E --> C
    C --> F["docker create或run"]
    F --> G["Container容器对象"]
    G --> H["容器可写层"]
    G --> I["Network网络端点"]
    G --> J["Volume或Bind Mount"]
    G --> K["stdout与stderr日志"]

删除影响不同:

操作删除什么默认不删除什么
docker stop不删除,只停止主进程容器、可写层、镜像、Volume
docker rm容器元数据和可写层镜像、普通命名卷
docker image rm本地镜像引用与无引用层容器、Volume
docker volume rm指定Volume及其数据镜像、容器
docker network rm指定网络对象容器、镜像、Volume

“停止”“删除容器”“删除镜像”“删除数据卷”是四件事。数据库数据是否保留,取决于它写在容器可写层、Volume、Bind Mount 还是外部存储。

三、先确认你操作的是哪台Docker Engine

3.1 Client和Server版本

bash
docker version

输出通常包含:

  • Client 版本。
  • Server/Engine 版本。
  • API 版本。
  • OS/Architecture。
  • containerd、runc 等组件版本。

只有 Client 信息而 Server 报错,通常表示 CLI 无法连接 daemon,而不是“没有安装 docker 命令”。

3.2 Engine总体信息

bash
docker info

重点关注:

  • Containers、Images 数量。
  • Storage Driver。
  • Logging Driver。
  • Cgroup Driver 和 Cgroup Version。
  • Docker Root Dir。
  • Registry Mirrors。
  • CPUs、Total Memory。
  • Operating System、Kernel Version。

docker info 可能包含内部地址和环境信息,分享前脱敏。

3.3 Context

bash
docker context ls
docker context show
docker --context default ps

多台主机、Docker Desktop 或远程 daemon 场景中,docker ps 只查询当前 context 对应的 Engine。生产操作前应记录 context、主机和项目,避免在错误环境执行删除或重启。

四、镜像名称、Tag、Digest与Image ID

镜像引用:

text
registry.example.com/order/order-api:1.8.3

拆解:

text
registry.example.com   Registry
order/order-api        Repository
1.8.3                  Tag

Digest 引用:

text
registry.example.com/order/order-api@sha256:...
标识特点
Tag可变引用,同一Tag可重新指向其他内容
Digest内容寻址,不同内容摘要不同
Image ID本地镜像配置内容的身份

生产发布记录应保存镜像 Digest,不能只记录 latest

五、镜像查询与精确筛选

5.1 列出镜像

bash
docker image ls
docker image ls --digests
docker image ls --no-trunc

常见列:

含义
REPOSITORY仓库名
TAG本地Tag
DIGEST从仓库获得的内容摘要,未必总显示
IMAGE ID本地镜像ID缩写
CREATED镜像配置创建时间,不等于拉取时间
SIZE镜像显示大小,层可能被多个镜像共享

5.2 Filter

bash
docker image ls --filter reference='order-api:*'
docker image ls --filter dangling=true
docker image ls --filter label=org.opencontainers.image.revision

dangling=true 只表示某些镜像结果当前没有普通名称引用,不等于一定可以无风险删除;仍要确认容器引用、构建缓存和回滚需求。

5.3 Format

bash
docker image ls \
  --format 'table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}'

适合脚本和报告,但字段名属于具体命令模板,不能假定所有命令都支持相同字段。

六、拉取镜像pull

bash
docker pull nginx:1.27
docker pull --platform linux/amd64 nginx:1.27

大致过程:

mermaid
flowchart TD
    A["解析Registry、Repository和Tag"] --> B["向Registry认证"]
    B --> C["获取Manifest或Manifest List"]
    C --> D["选择OS与CPU架构"]
    D --> E["检查本地已有Layer"]
    E --> F["只下载缺失Layer"]
    F --> G["校验内容Digest"]
    G --> H["写入本地镜像存储并记录引用"]

常见失败:

错误方向
manifest unknownTag或仓库路径不存在
unauthorized登录或仓库权限
no matching manifestOS/CPU架构不匹配
TLS错误CA、证书域名、系统时间、代理
timeoutDNS、网络、代理、Registry负载

拉取后验证:

bash
docker image inspect nginx:1.27
docker image ls --digests nginx

七、给镜像打Tag与推送

7.1 Tag不会复制镜像层

bash
docker tag order-api:1.8.3 registry.example.com/order/order-api:1.8.3

它为同一个本地镜像增加引用,不会重新构建,也不会产生一份完整层副本。

验证:

bash
docker image inspect order-api:1.8.3 --format '{{.Id}}'
docker image inspect registry.example.com/order/order-api:1.8.3 --format '{{.Id}}'

7.2 登录与推送

交互登录:

bash
docker login registry.example.com

CI 中避免把密码直接写在命令参数或日志。使用平台凭据绑定,通过标准输入:

bash
printf '%s' "$REGISTRY_PASSWORD" | \
  docker login registry.example.com \
    --username "$REGISTRY_USERNAME" \
    --password-stdin

推送:

bash
docker push registry.example.com/order/order-api:1.8.3

推送后应记录仓库返回的 Digest。Tag 可变,Digest 才能证明发布内容。

八、构建镜像build

bash
docker build -t order-api:dev .

最后的 . 是构建上下文,不是 Dockerfile 路径。

常用:

bash
docker build \
  --file Dockerfile \
  --tag order-api:dev \
  --build-arg GIT_COMMIT=a1b2c3d \
  --progress=plain \
  .

不使用缓存进行诊断:

bash
docker build --no-cache --progress=plain -t order-api:debug .

--no-cache 不应成为每次构建默认动作,否则失去层缓存价值;它适合验证是否被错误缓存掩盖,基础镜像是否更新仍受 pull 行为影响。

完整构建上下文、缓存、Secret、多阶段构建和 JDK 8/17 示例见 Dockerfile从构建原理到生产镜像

九、检查镜像inspecthistory

9.1 Image inspect

bash
docker image inspect order-api:dev

提取启动配置:

bash
docker image inspect \
  --format 'id={{.Id}} user={{.Config.User}} workdir={{.Config.WorkingDir}} entry={{json .Config.Entrypoint}} cmd={{json .Config.Cmd}} env={{json .Config.Env}} labels={{json .Config.Labels}}' \
  order-api:dev

Env 可能含敏感值,分享前脱敏。

9.2 History

bash
docker history order-api:dev
docker history --no-trunc order-api:dev

用于查看构建步骤与显示大小,帮助定位:

  • 哪一步复制了大文件。
  • 是否把 Maven/JDK 留在运行镜像。
  • 是否把源码、日志、Dump 复制进去。
  • 是否在不同层创建后又删除大文件。

History 不是完整供应链审计,仍需构建日志、SBOM、签名和源码关联。

十、docker run等于create加start

text
docker run ≈ docker create + docker start

它会:

  1. 解析镜像。
  2. 创建容器配置和可写层。
  3. 准备 namespace、cgroup、网络端点和挂载。
  4. 合并镜像 Entrypoint/Cmd 与运行参数。
  5. 启动容器主进程。

最小示例:

bash
docker run --name demo-nginx nginx:1.27

前台运行时,终端通常附着容器标准输出;按 Ctrl+C 可能向前台流程发送信号。实验环境清理前需要确认容器当前状态。

十一、run常用选项逐项解释

完整示例:

bash
docker run -d \
  --name demo-nginx \
  --hostname web-1 \
  --network demo-net \
  -p 127.0.0.1:18080:80 \
  --mount type=volume,source=demo-html,target=/usr/share/nginx/html \
  --memory=256m \
  --cpus=1 \
  --restart=unless-stopped \
  --label app=demo-nginx \
  nginx:1.27
选项作用常见误区
-d后台运行不代表应用健康
--name指定容器名容器名不是镜像名
--hostname设置容器UTS hostname不等于企业DNS注册
--network连接网络不应硬编码动态IP
-p发布宿主机端口Dockerfile EXPOSE不会自动发布
--mount挂载Volume/Bind/tmpfs挂载可能遮住镜像文件
--memory设置容器总内存限制Java Xmx不能等于全部限制
--cpus配置CPU配额CPU限流可能导致延迟高
--restart主进程退出后的重启策略不能修复启动配置错误
--label添加业务元数据不应放密码和敏感数据

11.1 -it到底是什么

bash
docker run --rm -it alpine:3.20 sh
  • -i 保持标准输入开放。
  • -t 分配伪终端。
  • --rm 主进程退出后自动删除该实验容器。

后台服务通常不需要 -it。生产容器使用 --rm 要理解退出后容器对象和可写层立即删除,现场 inspect 与可写层证据也会消失。

11.2 环境变量

bash
docker run --rm \
  -e SPRING_PROFILES_ACTIVE=test \
  -e LOG_LEVEL=INFO \
  order-api:dev

环境变量可被 inspect 和进程读取,不适合直接承载高价值密码。生产使用受控 Secret 系统,并避免日志打印。

使用文件:

bash
docker run --rm --env-file ./app.env order-api:dev

app.env 本身需要权限控制且不能提交敏感值到 Git。

11.3 端口格式

bash
docker run -p 127.0.0.1:18080:8080 order-api:dev

拆解:

text
127.0.0.1  宿主机绑定地址
18080      宿主机端口
8080       容器端口

应用还必须真正监听容器内 8080,并通常监听 0.0.0.0

十二、create、start、attach的区别

创建但不启动:

bash
docker create --name demo-nginx -p 18080:80 nginx:1.27

启动已有容器:

bash
docker start demo-nginx

启动并附着输出:

bash
docker start --attach demo-nginx

附着到运行中主进程标准流:

bash
docker attach demo-nginx

attach 连接主进程的标准流,不是在容器中创建新 Shell;按键和信号可能影响主进程。日常诊断更常用 logsexec

十三、列出容器ps

运行中:

bash
docker ps

包括已退出:

bash
docker ps -a

完整命令和状态:

bash
docker ps -a --no-trunc

过滤:

bash
docker ps -a --filter name=order-api
docker ps -a --filter status=exited
docker ps --filter label=app=order-api
docker ps -a --filter ancestor=order-api:1.8.3

格式化:

bash
docker ps -a \
  --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'

docker ps 没结果不等于容器从未存在,可能已经退出,应使用 -a。容器若已经删除,则需依赖外部日志、监控和审计。

十四、容器inspect怎么精确查询

完整 JSON:

bash
docker inspect order-api

状态:

bash
docker inspect --format '{{json .State}}' order-api

端口:

bash
docker inspect --format '{{json .NetworkSettings.Ports}}' order-api

网络:

bash
docker inspect --format '{{json .NetworkSettings.Networks}}' order-api

挂载:

bash
docker inspect --format '{{json .Mounts}}' order-api

资源限制:

bash
docker inspect \
  --format 'memory={{.HostConfig.Memory}} nanoCpus={{.HostConfig.NanoCpus}} pids={{.HostConfig.PidsLimit}}' \
  order-api

完整字段模型见 Docker容器信息与生产诊断

十五、停止、终止、重启的区别

15.1 stop

bash
docker stop --time 30 order-api

通常先向容器主进程发送停止信号,等待宽限时间;进程仍不退出再强制终止。Spring Boot 应利用宽限期停止接流量、处理在途请求并关闭资源。

15.2 kill

bash
docker kill --signal SIGTERM order-api

默认 docker kill 通常发送 SIGKILL,进程没有清理机会。生产除非明确需要,不应把强杀当成普通停止。

15.3 restart

bash
docker restart --time 30 order-api

重启的是同一个容器对象,不会自动使用一个新镜像创建容器,也不会重新计算 Compose 新环境变量和挂载。配置或镜像变化通常需要重建。

15.4 pause和unpause

bash
docker pause order-api
docker unpause order-api

pause 冻结容器进程执行,不是优雅停机。连接可能超时,锁和事务状态也可能长时间保持。生产使用必须明确业务影响。

十六、删除容器rm的边界

只删除明确、已确认的实验容器:

bash
docker ps -a --filter name=demo-nginx
docker inspect demo-nginx
docker rm demo-nginx

运行中容器默认不能直接删除。docker rm --force 会终止并删除,可能丢失可写层和事故证据,不应用作常规流程。

删除前回答:

  1. 容器是否仍承载流量。
  2. 容器可写层是否有唯一数据或 Dump。
  3. Mounts 中哪些是命名卷、Bind 或匿名卷。
  4. 日志是否已外部采集。
  5. 是否还需要 inspect、events 和启动配置取证。

本页不提供无条件删除全部容器的命令。批量操作必须由业务标签、项目归属和变更审批限定范围。

十七、查看日志logs

bash
docker logs order-api
docker logs --tail 200 order-api
docker logs --since 30m --timestamps order-api
docker logs --follow --tail 100 order-api

docker logs 读取日志驱动获得的 stdout/stderr。应用只写 /app/logs/app.log 时,Docker 不会自动读取该文件。

检查日志驱动:

bash
docker inspect --format '{{json .HostConfig.LogConfig}}' order-api
docker inspect --format '{{.LogPath}}' order-api

注意:

  • --follow 持续占用终端。
  • 多实例日志要带时间和实例身份。
  • 日志可能包含敏感业务数据。
  • 容器删除后本地日志可能不可用。
  • 生产需要集中日志和轮转。

十八、实时资源stats

bash
docker stats
docker stats order-api
docker stats --no-stream order-api

常见列:

含义
CPU %当前CPU使用,需结合核数和配额
MEM USAGE / LIMIT容器总内存使用和限制
MEM %使用比例
NET I/O累计网络收发
BLOCK I/O累计块设备读写
PIDS进程/线程任务数量

stats 是实时快照,不是历史监控。退出容器不再有当前资源值,必须依赖监控系统。

十九、进程top与容器内执行exec

19.1 top

bash
docker top order-api

从 Docker/宿主机视角查看容器进程,极简镜像中没有 ps 时仍可能有效。

19.2 exec

bash
docker exec order-api java -version
docker exec order-api printenv SPRING_PROFILES_ACTIVE
docker exec -it order-api sh

exec 的本质是在正在运行容器已有 namespace、cgroup、rootfs、网络和挂载环境中创建一个额外进程,不是 SSH 登录虚拟机。

限制:

  • 容器退出后不能 exec。
  • 镜像可能没有 Shell。
  • exec 进程也会消耗容器 PID、CPU 和内存。
  • 生产不要手工修改应用文件,重建后会丢失并破坏不可变交付。

19.3 exec参数位置

正确:

bash
docker exec --user 0 --workdir /tmp order-api id

order-api 后面的内容是容器内程序及参数。不要把 Docker exec 选项误放到容器名后。

二十、复制文件cp

从容器复制到当前目录:

bash
docker cp order-api:/app/logs/error.log ./error.log

从宿主机复制到容器:

bash
docker cp ./diagnostic.txt order-api:/tmp/diagnostic.txt

用途:

  • 导出日志、Dump、配置样本。
  • 在无 Shell 镜像中提取文件。
  • 实验环境临时传入诊断资料。

边界:

  • 复制生产文件可能含敏感数据。
  • 直接复制文件到运行容器不是发布方式。
  • 容器重建后手工复制内容会消失。
  • 大文件复制会占用 IO 和磁盘。

二十一、端口port

bash
docker port order-api
docker port order-api 8080/tcp

它显示容器端口对应的宿主机绑定。没有输出可能表示未发布,不代表容器内应用没有监听。

继续结合:

bash
docker inspect --format '{{json .NetworkSettings.Ports}}' order-api

详细 NAT 路径见 Docker网络底层原理

二十二、容器文件系统变化diff

bash
docker diff order-api

常见标记:

  • A:新增。
  • C:修改。
  • D:删除。

用于发现容器可写层变化,例如应用是否把日志、上传或临时文件写入镜像层。但输出只是路径变化,不替代文件内容审计,也不包含 Volume 内部的同等语义。

二十三、save/loadexport/import必须区分

23.1 save/load:保存镜像

bash
docker image save --output nginx-1.27.tar nginx:1.27
docker image load --input nginx-1.27.tar

保留镜像层、配置和标签信息,适合离线传输镜像。tar 文件可能很大,也需要校验、访问控制和来源验证。

23.2 export/import:导出容器文件系统快照

bash
docker container export --output demo-rootfs.tar demo-nginx
docker image import demo-rootfs.tar demo-imported:1.0

export 得到容器文件系统快照,不等同完整镜像备份:

  • 不保留原镜像分层历史。
  • 运行配置需要重新定义。
  • Volume 内容不包含在容器 rootfs 导出中。
  • 不适合作为数据库一致性备份。

所以迁移镜像通常使用 save/load 或 Registry,不要用 export/import 替代正常镜像流程。

二十四、网络命令

24.1 查询

bash
docker network ls
docker network inspect bridge

24.2 创建自定义bridge

bash
docker network create demo-net

可明确子网,但生产前需避免与宿主机、VPN、企业网络冲突:

bash
docker network create \
  --driver bridge \
  --subnet 172.30.0.0/24 \
  demo-net

24.3 连接和断开

bash
docker network connect demo-net demo-nginx
docker network disconnect demo-net demo-nginx

运行中改变网络可能影响现有连接和服务发现,生产操作前评估流量。

24.4 删除

先检查端点:

bash
docker network inspect demo-net

只删除已确认无业务端点的实验网络:

bash
docker network rm demo-net

Docker 不会允许随意删除仍被正常容器端点使用的网络,但不能把这个保护当作业务审批。

二十五、Volume命令

25.1 创建和查询

bash
docker volume create demo-html
docker volume ls
docker volume inspect demo-html

Inspect 重点:

  • Driver。
  • Mountpoint。
  • Labels。
  • Scope。
  • Options。

不要直接依赖宿主机 Mountpoint 手工修改数据库文件,应通过容器、数据库工具和受控备份流程操作。

25.2 挂载

推荐显式 --mount

bash
docker run -d \
  --name demo-nginx \
  --mount type=volume,source=demo-html,target=/usr/share/nginx/html \
  nginx:1.27

Bind Mount:

bash
docker run --rm \
  --mount type=bind,source="$PWD/config",target=/app/config,readonly \
  order-api:dev

PowerShell 的当前路径和引号规则不同,应先解析绝对路径,不要直接照抄 Bash $PWD

25.3 删除Volume是删除数据

先查引用和业务归属:

bash
docker volume inspect demo-html
docker ps -a --filter volume=demo-html

只对明确的实验卷执行:

bash
docker volume rm demo-html

本页不提供无条件 volume prune 作为日常操作。未被当前容器引用的卷仍可能包含停止环境、事故现场或待恢复数据。

二十六、系统空间和事件

26.1 空间统计

bash
docker system df
docker system df -v

用于区分:

  • Images。
  • Containers。
  • Local Volumes。
  • Build Cache。

Reclaimable 只是 Docker 视角的可回收估计,不等于业务允许删除。

26.2 Events

bash
docker events --since 30m
docker events --since 30m --filter container=order-api
docker events --since 30m --filter event=die

events 是流式输出,可指定时间范围和 filter。它能帮助构建 create、start、health、die、stop、destroy 等时间线,但生产历史事件最好外部持续采集。

二十七、Buildx与多平台基础

查看 builder:

bash
docker buildx ls
docker buildx inspect

多平台构建示例:

bash
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --tag registry.example.com/order/order-api:1.8.3 \
  --push \
  .

多平台结果通常是 manifest list/index,指向不同架构镜像。构建成功不代表 JNI、本地库和运行行为已在每个平台测试,仍需架构对应测试环境。

单平台加载到本地 Engine:

bash
docker buildx build \
  --platform linux/amd64 \
  --tag order-api:amd64-test \
  --load \
  .

二十八、Compose命令入口

bash
docker compose config
docker compose pull
docker compose build
docker compose up -d --wait
docker compose ps -a
docker compose logs --tail 200
docker compose top
docker compose images
docker compose stop
docker compose down

重要区别:

  • stop 保留容器和网络对象。
  • down 删除项目容器和默认网络,普通命名卷默认保留。
  • down -v 可能删除项目卷和数据。
  • restart 不会必然加载新的环境、端口和挂载。
  • up -d 才会按当前项目模型协调和必要重建。

完整原理见 Docker Compose从项目模型到商业编排

二十九、安全删除与清理流程

旧式速查表常给出“删除全部容器、全部镜像、全部卷”的命令,这是危险文档模式。正确过程:

mermaid
flowchart TD
    A["发现Docker磁盘占用"] --> B["docker system df -v分类"]
    B --> C["按label、项目和时间定位对象"]
    C --> D["检查容器引用、Mounts和业务归属"]
    D --> E["确认备份、回滚与恢复"]
    E --> F["只删除明确目标对象"]
    F --> G["复查磁盘、服务和审计记录"]

29.1 删除容器前

bash
docker ps -a --filter name=demo-nginx
docker inspect demo-nginx

确认是实验对象后:

bash
docker stop demo-nginx
docker rm demo-nginx

29.2 删除镜像前

bash
docker image inspect nginx:1.27
docker ps -a --filter ancestor=nginx:1.27

确认没有保留和回滚需求后:

bash
docker image rm nginx:1.27

Image Tag 可能只是多个引用之一。删除一个 Tag 不一定释放层;仍被其他 Tag 或容器引用的内容会保留。

29.3 删除Volume前

bash
docker volume inspect demo-html
docker ps -a --filter volume=demo-html

确认数据无价值或已有可恢复备份后,才对明确名称执行 docker volume rm

29.4 为什么不直接执行全局prune

Prune 类命令通常没有理解业务语义的能力。它只根据 Docker 引用状态判断“未使用”,但业务可能认为某个停止环境的 Volume、旧镜像或构建缓存仍用于回滚和恢复。

生产必须把:

  • 对象标签。
  • 保留期限。
  • 镜像仓库策略。
  • 构建缓存策略。
  • Volume备份。
  • 变更审批。

结合起来治理,而不是定期无条件清空。

三十、可运行实验:Nginx完整生命周期

本实验只创建带 training=docker-command 标签的明确对象。

30.1 创建网络和Volume

bash
docker network create --label training=docker-command command-demo-net
docker volume create --label training=docker-command command-demo-html

确认:

bash
docker network inspect command-demo-net
docker volume inspect command-demo-html

30.2 写入首页

使用一次性容器写入 Volume:

bash
docker run --rm \
  --mount type=volume,source=command-demo-html,target=/data \
  alpine:3.20 \
  sh -c 'printf "%s\n" "<h1>Docker command demo</h1>" > /data/index.html'

这里一次性容器删除后,命名卷仍保留。

30.3 运行Nginx

bash
docker run -d \
  --name command-demo-nginx \
  --label training=docker-command \
  --network command-demo-net \
  -p 127.0.0.1:18080:80 \
  --mount type=volume,source=command-demo-html,target=/usr/share/nginx/html,readonly \
  --memory=128m \
  --cpus=1 \
  --restart=no \
  nginx:1.27

30.4 逐层验证

bash
docker ps --filter label=training=docker-command
docker inspect command-demo-nginx
docker port command-demo-nginx
docker stats --no-stream command-demo-nginx
docker top command-demo-nginx
docker logs --tail 100 command-demo-nginx
curl -v http://127.0.0.1:18080/

容器内验证配置:

bash
docker exec command-demo-nginx nginx -T

复制配置样本:

bash
docker cp command-demo-nginx:/etc/nginx/nginx.conf ./command-demo-nginx.conf

30.5 停止和再次启动

bash
docker stop --time 10 command-demo-nginx
docker ps -a --filter name=command-demo-nginx
docker start command-demo-nginx
curl -v http://127.0.0.1:18080/

这证明 stop 不会删除容器,也不会删除命名卷。

30.6 安全清理实验对象

先列出并确认:

bash
docker ps -a --filter label=training=docker-command
docker network ls --filter label=training=docker-command
docker volume ls --filter label=training=docker-command

仅清理本实验明确名称:

bash
docker stop command-demo-nginx
docker rm command-demo-nginx
docker network rm command-demo-net
docker volume rm command-demo-html

如果对象不存在,命令会报错;如果 Volume 仍被引用,应重新检查引用,不要直接强制删除。

三十一、商业场景:确认线上容器到底运行哪个版本

用户反馈订单接口在发布后异常,部署记录写的是 order-api:latest。不能只执行:

bash
docker ps

完整检查:

bash
docker ps -a --filter name=order-api --no-trunc
docker inspect --format 'container={{.Name}} imageId={{.Image}} started={{.State.StartedAt}} labels={{json .Config.Labels}}' order-api
docker image inspect --format 'id={{.Id}} repoDigests={{json .RepoDigests}} labels={{json .Config.Labels}} created={{.Created}}' order-api:latest
docker events --since 2h --filter container=order-api

需要回答:

  1. 当前容器绑定的不可变 Image ID 是什么。
  2. 本地 latest 当前指向什么,是否与运行容器相同。
  3. RepoDigest 是什么。
  4. 镜像 Label 中的 Git commit 是什么。
  5. 容器何时创建、何时启动。
  6. 发布期间是否发生 destroy/create,而不是简单 restart。

因此生产不能只用 latest。应使用版本或 commit Tag,并把 Digest 记录进部署系统。

三十二、常见命令误区

误区实际情况正确方向
docker ps没有就是容器不存在只显示运行中容器使用docker ps -a
restart后用了新镜像restart仍是原容器pull后重建并inspect Image ID
EXPOSE后外部能访问EXPOSE只是镜像元数据使用-p并确认监听
logs包含所有日志只读取日志驱动接收的输出检查应用文件日志和LogConfig
exec是登录虚拟机它创建额外进程理解namespace和容器生命周期
stop会删除容器只停止主进程rm才删除容器对象
rm容器会删除命名卷默认通常不会查看Mounts和卷生命周期
rmi会删除运行容器镜像和容器是不同对象先查容器引用关系
export等于镜像备份只是容器rootfs快照镜像用save/load或Registry
Volume就是备份只是独立生命周期设计独立副本与恢复演练
prune都可安全执行Docker不懂业务保留语义先分类、确认、备份、精确删除

三十三、面试标准回答

docker run背后做了什么

docker run可以理解为create加start。Docker根据镜像和运行参数生成容器配置,准备镜像只读层与容器可写层、Mount、Network Namespace、cgroup和端口发布,合并镜像Entrypoint/Cmd与运行参数,再由daemon通过containerd、OCI runtime启动主进程。主进程退出后容器进入Exited,命名卷通常仍独立保留。

docker stop、kill、restart区别

stop先向主进程发送停止信号并等待宽限期,超时才强杀;kill默认通常直接发送SIGKILL,也可指定信号;restart对同一容器执行停止再启动,不会自动使用新镜像重建,也不会必然加载Compose的新环境、端口和挂载。生产优先优雅stop,配置或镜像变化走受控重建。

docker exec和attach区别

exec在运行容器已有namespace和cgroup中创建一个额外进程,常用于执行诊断命令;attach连接容器主进程已有标准输入输出,不创建新Shell,按键和信号可能影响主进程。容器退出后不能exec,但仍可能inspect和logs。

save/load与export/import区别

save/load面向镜像,保留镜像层、配置和标签,适合离线镜像传输;export导出容器rootfs快照,import生成扁平化镜像,不保留原分层和完整运行配置,也不包含Volume数据。迁移镜像优先Registry或save/load,数据库备份必须使用数据库一致性方案。

删除容器、镜像和Volume分别影响什么

rm容器删除容器元数据和可写层,普通命名卷和镜像默认保留;image rm删除本地镜像引用和无引用层,不会删除Volume;volume rm直接删除指定卷的数据。删除前必须检查容器状态、Mounts、对象引用、业务归属和备份,不能用无条件批量命令或prune代替判断。

docker logs为什么可能没有应用日志

logs读取Docker日志驱动接收的容器stdout/stderr。应用如果只写容器内文件,Docker不会自动读取;还要检查LogConfig、LogPath、应用日志配置和Mounts。容器删除后本地日志可能消失,所以生产需要集中采集和轮转。

三十四、学习验收

不看答案完成:

  1. 解释当前 Docker context、Client与Server版本、Root Dir和cgroup模式。
  2. 拉取镜像并记录Tag、Digest、Image ID三者。
  3. 从Dockerfile构建镜像,用inspect验证User、Entrypoint、Cmd和Labels。
  4. 分别使用create/start和run创建容器,说明对象差异。
  5. 使用filter、format和label只定位目标实验对象。
  6. 使用inspect、logs、stats、top、exec、cp、port和events完成诊断。
  7. 创建网络和Volume,解释容器删除后哪些数据保留。
  8. 证明restart没有自动切换到新镜像。
  9. 比较save/load与export/import生成结果。
  10. 在不使用全局批量删除和prune的情况下,安全清理明确实验对象。

关联知识点