Docker 命令从对象模型到生产操作
Docker 命令不是一组需要死记的缩写。每条命令都在读取或改变某个对象:context、image、container、network、volume、builder 或 Compose project。真正需要掌握的是命令的输入对象、产生的状态变化、数据是否保留、输出如何判读,以及命令失败后应该查哪一层。
本页以“对象 → 生命周期 → 只读检查 → 状态变更 → 风险边界”组织命令。容器字段的深入判读见 Docker容器信息与生产诊断,事故决策流程见 Docker生产故障排查Runbook。
学习目标
学完后,应能:
- 看懂
docker [管理对象] [动作] [选项] [对象]的命令结构。 - 区分 image、container、network、volume、context、builder 和 Compose project。
- 正确解释 create、start、run、stop、kill、restart、rm 的状态变化。
- 正确使用 pull、tag、push、save/load,并区分 export/import。
- 使用 filter、format、inspect 和 label 精确定位对象,而不是复制 ID 后盲目操作。
- 使用 logs、stats、top、exec、cp、events 完成运行中和已退出容器诊断。
- 创建网络和 Volume,理解删除容器、镜像和卷对数据的不同影响。
- 执行删除与清理前证明目标对象、引用关系、业务归属和恢复能力。
- 完成一个从拉镜像、运行、验证、修改、停止到安全清理的可重复实验。
一、先读懂Docker CLI命令结构
现代 Docker CLI 常见结构:
docker <management-command> <subcommand> [OPTIONS] [ARGUMENTS]例如:
docker container ls --all
docker image inspect nginx:1.27
docker network create demo-net
docker volume inspect demo-data也有兼容的短写:
docker ps -a
docker images
docker inspect nginx:1.27建议初学时先理解完整对象形式,再使用熟悉的短写:
| 完整形式 | 常见短写 | 对象 |
|---|---|---|
docker container ls | docker ps | Container |
docker image ls | docker images | Image |
docker container rm | docker rm | Container |
docker image rm | docker rmi | Image |
1.1 命令帮助是第一手边界说明
docker --help
docker container --help
docker run --help
docker inspect --help不同 Docker/Compose 版本支持的选项可能不同。遇到教程参数不可用,先执行:
docker version
docker compose version
docker <命令> --help不要先假定安装损坏。
1.2 选项位置为什么重要
Docker CLI 全局选项和子命令选项作用域不同:
docker --context prod container ls这里 --context 作用于 Docker CLI 连接目标。
docker container ls --all这里 --all 作用于 container ls。
运行容器时,镜像名前是 Docker 的 run 参数,镜像名后的内容通常是传给容器的命令或参数:
docker run --name demo nginx:1.27 nginx -T拆解:
docker run Docker动作
--name demo run选项
nginx:1.27 镜像
nginx -T 覆盖或传给容器的命令参数把 -p、-e 放到镜像名后面,可能不再被 Docker 当作 run 选项,而是传给镜像入口程序。
二、Docker对象关系与数据生命周期
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版本
docker version输出通常包含:
- Client 版本。
- Server/Engine 版本。
- API 版本。
- OS/Architecture。
- containerd、runc 等组件版本。
只有 Client 信息而 Server 报错,通常表示 CLI 无法连接 daemon,而不是“没有安装 docker 命令”。
3.2 Engine总体信息
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
docker context ls
docker context show
docker --context default ps多台主机、Docker Desktop 或远程 daemon 场景中,docker ps 只查询当前 context 对应的 Engine。生产操作前应记录 context、主机和项目,避免在错误环境执行删除或重启。
四、镜像名称、Tag、Digest与Image ID
镜像引用:
registry.example.com/order/order-api:1.8.3拆解:
registry.example.com Registry
order/order-api Repository
1.8.3 TagDigest 引用:
registry.example.com/order/order-api@sha256:...| 标识 | 特点 |
|---|---|
| Tag | 可变引用,同一Tag可重新指向其他内容 |
| Digest | 内容寻址,不同内容摘要不同 |
| Image ID | 本地镜像配置内容的身份 |
生产发布记录应保存镜像 Digest,不能只记录 latest。
五、镜像查询与精确筛选
5.1 列出镜像
docker image ls
docker image ls --digests
docker image ls --no-trunc常见列:
| 列 | 含义 |
|---|---|
| REPOSITORY | 仓库名 |
| TAG | 本地Tag |
| DIGEST | 从仓库获得的内容摘要,未必总显示 |
| IMAGE ID | 本地镜像ID缩写 |
| CREATED | 镜像配置创建时间,不等于拉取时间 |
| SIZE | 镜像显示大小,层可能被多个镜像共享 |
5.2 Filter
docker image ls --filter reference='order-api:*'
docker image ls --filter dangling=true
docker image ls --filter label=org.opencontainers.image.revisiondangling=true 只表示某些镜像结果当前没有普通名称引用,不等于一定可以无风险删除;仍要确认容器引用、构建缓存和回滚需求。
5.3 Format
docker image ls \
--format 'table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}'适合脚本和报告,但字段名属于具体命令模板,不能假定所有命令都支持相同字段。
六、拉取镜像pull
docker pull nginx:1.27
docker pull --platform linux/amd64 nginx:1.27大致过程:
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 unknown | Tag或仓库路径不存在 |
unauthorized | 登录或仓库权限 |
no matching manifest | OS/CPU架构不匹配 |
| TLS错误 | CA、证书域名、系统时间、代理 |
| timeout | DNS、网络、代理、Registry负载 |
拉取后验证:
docker image inspect nginx:1.27
docker image ls --digests nginx七、给镜像打Tag与推送
7.1 Tag不会复制镜像层
docker tag order-api:1.8.3 registry.example.com/order/order-api:1.8.3它为同一个本地镜像增加引用,不会重新构建,也不会产生一份完整层副本。
验证:
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 登录与推送
交互登录:
docker login registry.example.comCI 中避免把密码直接写在命令参数或日志。使用平台凭据绑定,通过标准输入:
printf '%s' "$REGISTRY_PASSWORD" | \
docker login registry.example.com \
--username "$REGISTRY_USERNAME" \
--password-stdin推送:
docker push registry.example.com/order/order-api:1.8.3推送后应记录仓库返回的 Digest。Tag 可变,Digest 才能证明发布内容。
八、构建镜像build
docker build -t order-api:dev .最后的 . 是构建上下文,不是 Dockerfile 路径。
常用:
docker build \
--file Dockerfile \
--tag order-api:dev \
--build-arg GIT_COMMIT=a1b2c3d \
--progress=plain \
.不使用缓存进行诊断:
docker build --no-cache --progress=plain -t order-api:debug .--no-cache 不应成为每次构建默认动作,否则失去层缓存价值;它适合验证是否被错误缓存掩盖,基础镜像是否更新仍受 pull 行为影响。
完整构建上下文、缓存、Secret、多阶段构建和 JDK 8/17 示例见 Dockerfile从构建原理到生产镜像。
九、检查镜像inspect与history
9.1 Image inspect
docker image inspect order-api:dev提取启动配置:
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:devEnv 可能含敏感值,分享前脱敏。
9.2 History
docker history order-api:dev
docker history --no-trunc order-api:dev用于查看构建步骤与显示大小,帮助定位:
- 哪一步复制了大文件。
- 是否把 Maven/JDK 留在运行镜像。
- 是否把源码、日志、Dump 复制进去。
- 是否在不同层创建后又删除大文件。
History 不是完整供应链审计,仍需构建日志、SBOM、签名和源码关联。
十、docker run等于create加start
docker run ≈ docker create + docker start它会:
- 解析镜像。
- 创建容器配置和可写层。
- 准备 namespace、cgroup、网络端点和挂载。
- 合并镜像 Entrypoint/Cmd 与运行参数。
- 启动容器主进程。
最小示例:
docker run --name demo-nginx nginx:1.27前台运行时,终端通常附着容器标准输出;按 Ctrl+C 可能向前台流程发送信号。实验环境清理前需要确认容器当前状态。
十一、run常用选项逐项解释
完整示例:
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到底是什么
docker run --rm -it alpine:3.20 sh-i保持标准输入开放。-t分配伪终端。--rm主进程退出后自动删除该实验容器。
后台服务通常不需要 -it。生产容器使用 --rm 要理解退出后容器对象和可写层立即删除,现场 inspect 与可写层证据也会消失。
11.2 环境变量
docker run --rm \
-e SPRING_PROFILES_ACTIVE=test \
-e LOG_LEVEL=INFO \
order-api:dev环境变量可被 inspect 和进程读取,不适合直接承载高价值密码。生产使用受控 Secret 系统,并避免日志打印。
使用文件:
docker run --rm --env-file ./app.env order-api:devapp.env 本身需要权限控制且不能提交敏感值到 Git。
11.3 端口格式
docker run -p 127.0.0.1:18080:8080 order-api:dev拆解:
127.0.0.1 宿主机绑定地址
18080 宿主机端口
8080 容器端口应用还必须真正监听容器内 8080,并通常监听 0.0.0.0。
十二、create、start、attach的区别
创建但不启动:
docker create --name demo-nginx -p 18080:80 nginx:1.27启动已有容器:
docker start demo-nginx启动并附着输出:
docker start --attach demo-nginx附着到运行中主进程标准流:
docker attach demo-nginxattach 连接主进程的标准流,不是在容器中创建新 Shell;按键和信号可能影响主进程。日常诊断更常用 logs 或 exec。
十三、列出容器ps
运行中:
docker ps包括已退出:
docker ps -a完整命令和状态:
docker ps -a --no-trunc过滤:
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格式化:
docker ps -a \
--format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'docker ps 没结果不等于容器从未存在,可能已经退出,应使用 -a。容器若已经删除,则需依赖外部日志、监控和审计。
十四、容器inspect怎么精确查询
完整 JSON:
docker inspect order-api状态:
docker inspect --format '{{json .State}}' order-api端口:
docker inspect --format '{{json .NetworkSettings.Ports}}' order-api网络:
docker inspect --format '{{json .NetworkSettings.Networks}}' order-api挂载:
docker inspect --format '{{json .Mounts}}' order-api资源限制:
docker inspect \
--format 'memory={{.HostConfig.Memory}} nanoCpus={{.HostConfig.NanoCpus}} pids={{.HostConfig.PidsLimit}}' \
order-api完整字段模型见 Docker容器信息与生产诊断。
十五、停止、终止、重启的区别
15.1 stop
docker stop --time 30 order-api通常先向容器主进程发送停止信号,等待宽限时间;进程仍不退出再强制终止。Spring Boot 应利用宽限期停止接流量、处理在途请求并关闭资源。
15.2 kill
docker kill --signal SIGTERM order-api默认 docker kill 通常发送 SIGKILL,进程没有清理机会。生产除非明确需要,不应把强杀当成普通停止。
15.3 restart
docker restart --time 30 order-api重启的是同一个容器对象,不会自动使用一个新镜像创建容器,也不会重新计算 Compose 新环境变量和挂载。配置或镜像变化通常需要重建。
15.4 pause和unpause
docker pause order-api
docker unpause order-apipause 冻结容器进程执行,不是优雅停机。连接可能超时,锁和事务状态也可能长时间保持。生产使用必须明确业务影响。
十六、删除容器rm的边界
只删除明确、已确认的实验容器:
docker ps -a --filter name=demo-nginx
docker inspect demo-nginx
docker rm demo-nginx运行中容器默认不能直接删除。docker rm --force 会终止并删除,可能丢失可写层和事故证据,不应用作常规流程。
删除前回答:
- 容器是否仍承载流量。
- 容器可写层是否有唯一数据或 Dump。
- Mounts 中哪些是命名卷、Bind 或匿名卷。
- 日志是否已外部采集。
- 是否还需要 inspect、events 和启动配置取证。
本页不提供无条件删除全部容器的命令。批量操作必须由业务标签、项目归属和变更审批限定范围。
十七、查看日志logs
docker logs order-api
docker logs --tail 200 order-api
docker logs --since 30m --timestamps order-api
docker logs --follow --tail 100 order-apidocker logs 读取日志驱动获得的 stdout/stderr。应用只写 /app/logs/app.log 时,Docker 不会自动读取该文件。
检查日志驱动:
docker inspect --format '{{json .HostConfig.LogConfig}}' order-api
docker inspect --format '{{.LogPath}}' order-api注意:
--follow持续占用终端。- 多实例日志要带时间和实例身份。
- 日志可能包含敏感业务数据。
- 容器删除后本地日志可能不可用。
- 生产需要集中日志和轮转。
十八、实时资源stats
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
docker top order-api从 Docker/宿主机视角查看容器进程,极简镜像中没有 ps 时仍可能有效。
19.2 exec
docker exec order-api java -version
docker exec order-api printenv SPRING_PROFILES_ACTIVE
docker exec -it order-api shexec 的本质是在正在运行容器已有 namespace、cgroup、rootfs、网络和挂载环境中创建一个额外进程,不是 SSH 登录虚拟机。
限制:
- 容器退出后不能 exec。
- 镜像可能没有 Shell。
- exec 进程也会消耗容器 PID、CPU 和内存。
- 生产不要手工修改应用文件,重建后会丢失并破坏不可变交付。
19.3 exec参数位置
正确:
docker exec --user 0 --workdir /tmp order-api idorder-api 后面的内容是容器内程序及参数。不要把 Docker exec 选项误放到容器名后。
二十、复制文件cp
从容器复制到当前目录:
docker cp order-api:/app/logs/error.log ./error.log从宿主机复制到容器:
docker cp ./diagnostic.txt order-api:/tmp/diagnostic.txt用途:
- 导出日志、Dump、配置样本。
- 在无 Shell 镜像中提取文件。
- 实验环境临时传入诊断资料。
边界:
- 复制生产文件可能含敏感数据。
- 直接复制文件到运行容器不是发布方式。
- 容器重建后手工复制内容会消失。
- 大文件复制会占用 IO 和磁盘。
二十一、端口port
docker port order-api
docker port order-api 8080/tcp它显示容器端口对应的宿主机绑定。没有输出可能表示未发布,不代表容器内应用没有监听。
继续结合:
docker inspect --format '{{json .NetworkSettings.Ports}}' order-api详细 NAT 路径见 Docker网络底层原理。
二十二、容器文件系统变化diff
docker diff order-api常见标记:
A:新增。C:修改。D:删除。
用于发现容器可写层变化,例如应用是否把日志、上传或临时文件写入镜像层。但输出只是路径变化,不替代文件内容审计,也不包含 Volume 内部的同等语义。
二十三、save/load与export/import必须区分
23.1 save/load:保存镜像
docker image save --output nginx-1.27.tar nginx:1.27
docker image load --input nginx-1.27.tar保留镜像层、配置和标签信息,适合离线传输镜像。tar 文件可能很大,也需要校验、访问控制和来源验证。
23.2 export/import:导出容器文件系统快照
docker container export --output demo-rootfs.tar demo-nginx
docker image import demo-rootfs.tar demo-imported:1.0export 得到容器文件系统快照,不等同完整镜像备份:
- 不保留原镜像分层历史。
- 运行配置需要重新定义。
- Volume 内容不包含在容器 rootfs 导出中。
- 不适合作为数据库一致性备份。
所以迁移镜像通常使用 save/load 或 Registry,不要用 export/import 替代正常镜像流程。
二十四、网络命令
24.1 查询
docker network ls
docker network inspect bridge24.2 创建自定义bridge
docker network create demo-net可明确子网,但生产前需避免与宿主机、VPN、企业网络冲突:
docker network create \
--driver bridge \
--subnet 172.30.0.0/24 \
demo-net24.3 连接和断开
docker network connect demo-net demo-nginx
docker network disconnect demo-net demo-nginx运行中改变网络可能影响现有连接和服务发现,生产操作前评估流量。
24.4 删除
先检查端点:
docker network inspect demo-net只删除已确认无业务端点的实验网络:
docker network rm demo-netDocker 不会允许随意删除仍被正常容器端点使用的网络,但不能把这个保护当作业务审批。
二十五、Volume命令
25.1 创建和查询
docker volume create demo-html
docker volume ls
docker volume inspect demo-htmlInspect 重点:
- Driver。
- Mountpoint。
- Labels。
- Scope。
- Options。
不要直接依赖宿主机 Mountpoint 手工修改数据库文件,应通过容器、数据库工具和受控备份流程操作。
25.2 挂载
推荐显式 --mount:
docker run -d \
--name demo-nginx \
--mount type=volume,source=demo-html,target=/usr/share/nginx/html \
nginx:1.27Bind Mount:
docker run --rm \
--mount type=bind,source="$PWD/config",target=/app/config,readonly \
order-api:devPowerShell 的当前路径和引号规则不同,应先解析绝对路径,不要直接照抄 Bash $PWD。
25.3 删除Volume是删除数据
先查引用和业务归属:
docker volume inspect demo-html
docker ps -a --filter volume=demo-html只对明确的实验卷执行:
docker volume rm demo-html本页不提供无条件 volume prune 作为日常操作。未被当前容器引用的卷仍可能包含停止环境、事故现场或待恢复数据。
二十六、系统空间和事件
26.1 空间统计
docker system df
docker system df -v用于区分:
- Images。
- Containers。
- Local Volumes。
- Build Cache。
Reclaimable 只是 Docker 视角的可回收估计,不等于业务允许删除。
26.2 Events
docker events --since 30m
docker events --since 30m --filter container=order-api
docker events --since 30m --filter event=dieevents 是流式输出,可指定时间范围和 filter。它能帮助构建 create、start、health、die、stop、destroy 等时间线,但生产历史事件最好外部持续采集。
二十七、Buildx与多平台基础
查看 builder:
docker buildx ls
docker buildx inspect多平台构建示例:
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag registry.example.com/order/order-api:1.8.3 \
--push \
.多平台结果通常是 manifest list/index,指向不同架构镜像。构建成功不代表 JNI、本地库和运行行为已在每个平台测试,仍需架构对应测试环境。
单平台加载到本地 Engine:
docker buildx build \
--platform linux/amd64 \
--tag order-api:amd64-test \
--load \
.二十八、Compose命令入口
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从项目模型到商业编排。
二十九、安全删除与清理流程
旧式速查表常给出“删除全部容器、全部镜像、全部卷”的命令,这是危险文档模式。正确过程:
flowchart TD
A["发现Docker磁盘占用"] --> B["docker system df -v分类"]
B --> C["按label、项目和时间定位对象"]
C --> D["检查容器引用、Mounts和业务归属"]
D --> E["确认备份、回滚与恢复"]
E --> F["只删除明确目标对象"]
F --> G["复查磁盘、服务和审计记录"]29.1 删除容器前
docker ps -a --filter name=demo-nginx
docker inspect demo-nginx确认是实验对象后:
docker stop demo-nginx
docker rm demo-nginx29.2 删除镜像前
docker image inspect nginx:1.27
docker ps -a --filter ancestor=nginx:1.27确认没有保留和回滚需求后:
docker image rm nginx:1.27Image Tag 可能只是多个引用之一。删除一个 Tag 不一定释放层;仍被其他 Tag 或容器引用的内容会保留。
29.3 删除Volume前
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
docker network create --label training=docker-command command-demo-net
docker volume create --label training=docker-command command-demo-html确认:
docker network inspect command-demo-net
docker volume inspect command-demo-html30.2 写入首页
使用一次性容器写入 Volume:
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
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.2730.4 逐层验证
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/容器内验证配置:
docker exec command-demo-nginx nginx -T复制配置样本:
docker cp command-demo-nginx:/etc/nginx/nginx.conf ./command-demo-nginx.conf30.5 停止和再次启动
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 安全清理实验对象
先列出并确认:
docker ps -a --filter label=training=docker-command
docker network ls --filter label=training=docker-command
docker volume ls --filter label=training=docker-command仅清理本实验明确名称:
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。不能只执行:
docker ps完整检查:
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需要回答:
- 当前容器绑定的不可变 Image ID 是什么。
- 本地
latest当前指向什么,是否与运行容器相同。 - RepoDigest 是什么。
- 镜像 Label 中的 Git commit 是什么。
- 容器何时创建、何时启动。
- 发布期间是否发生 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。容器删除后本地日志可能消失,所以生产需要集中采集和轮转。
三十四、学习验收
不看答案完成:
- 解释当前 Docker context、Client与Server版本、Root Dir和cgroup模式。
- 拉取镜像并记录Tag、Digest、Image ID三者。
- 从Dockerfile构建镜像,用inspect验证User、Entrypoint、Cmd和Labels。
- 分别使用create/start和run创建容器,说明对象差异。
- 使用filter、format和label只定位目标实验对象。
- 使用inspect、logs、stats、top、exec、cp、port和events完成诊断。
- 创建网络和Volume,解释容器删除后哪些数据保留。
- 证明restart没有自动切换到新镜像。
- 比较save/load与export/import生成结果。
- 在不使用全局批量删除和prune的情况下,安全清理明确实验对象。
