docker 命令详解与参数实测(Ubuntu 22.04)

以 Ubuntu 22.04(Docker 29.1.3,docker.io 包)实测逐用法讲解 docker:run 参数组(-d/--name/--rm/-e/-w/--hostname/--entrypoint/--restart)、ps 过滤与 --format、images 参数组与 pull/tag/rmi/prune/search、inspect/history/save、exec 参数组、logs(实测 exec 输出不进日志)/top/stats、pause/unpause/rename/restart/stop/start/kill、cp/diff/commit、export/import、network 全套与内嵌 DNS、volume 与 bind 挂载、build 与 legacy builder 提示、system df/prune,附 dockerd 代理启动与 vfs 存储驱动说明,全部命令与回显实测通过。

Linux命令DockerLinux系统UbuntuUbuntu 22.04命令行2026/10/17

docker 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 docker 命令的核心用法——run 参数组(-d/--name/--rm/-e/-w/--hostname/--entrypoint/--restart)、ps 过滤与 --format 自定义输出、images 参数组与 pull/tag/rmi/prune/search、inspect 与 history、exec 参数组(-d/-e/-w/-u 与目标不存在时的报错)、logs(实测 exec 输出不进日志)/top/stats、pause/unpause/rename/restart/stop/start/kill 生命周期、cp/diff/commit 快照、export/import、network 全套(create/inspect/connect/disconnect/rm 与内嵌 DNS 解析)、volume 全套(create/inspect/占用时删除报错)与 bind 挂载、build 构建 Dockerfile(legacy builder 弃用提示)、system df 与 prune,全部命令与回显已在 Ubuntu 22.04(Docker 29.1.3)实测通过。

一、环境信息

本文所有命令均在以下环境实测,回显逐字照抄:

  • 操作系统:Ubuntu 22.04.5 LTS
  • Docker:docker.io 软件包,Docker version 29.1.3, build 29.1.3-0ubuntu3~22.04.2(Ubuntu 22.04 软件源版本)
  • 存储驱动:vfs(docker info 实测显示 Storage Driver: vfs,嵌套环境 overlay 挂载受限时的稳妥选择)
  • Cgroup:Version 2,驱动 cgroupfs;内核 6.8.0-138-generic
  • 执行身份:root
  • 测试镜像:hello-world:latest(10.1kB)、ubuntu:22.04(78.1MB)

安装与守护进程启动(镜像仓库访问走代理):

apt-get update && apt-get install -y docker.io
# 带代理后台启动 dockerd(拉取镜像走 HTTP 代理,本地回环不走代理)
env HTTP_PROXY=http://192.168.1.62:7897 \
    HTTPS_PROXY=http://192.168.1.62:7897 \
    NO_PROXY=localhost,127.0.0.1 \
    dockerd --storage-driver=vfs > /var/log/dockerd.log 2>&1 &
$ docker info(节选关键字段)
 Server Version: 29.1.3
 Storage Driver: vfs
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Kernel Version: 6.8.0-138-generic
 Operating System: Ubuntu 22.04.5 LTS
 CPUs: 12
 Total Memory: 31.3GiB
退出码=0

二、命令概览

2.1 语法形态

docker CLI 形态为「docker 管理对象 + 动作 + 参数」:

docker [OPTIONS] COMMAND [ARG...]

管理对象即 container、image、network、volume、system 五大类;同时 docker 为高频动作保留了短命令别名:docker ps = docker container ls、docker images = docker image ls、docker run = docker container run、docker rmi = docker image rm。本文按短命令实测。

2.2 版本信息

$ docker --version
Docker version 29.1.3, build 29.1.3-0ubuntu3~22.04.2
退出码=0

$ docker version(客户端与服务端版本,节选)
Client:
 Version:           29.1.3
 API version:       1.52
 Go version:        go1.24.4
 Git commit:        29.1.3-0ubuntu3~22.04.2
 Built:             Wed Apr 29 22:18:59 2026
 OS/Arch:           linux/amd64
 Context:           default

Server:
 Engine:
  Version:          29.1.3
退出码=0

2.3 磁盘总览:docker system df

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          2         0         78.1MB    0B (0%)
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B
退出码=0

-v 展开逐对象明细(3.14 实测),是排查磁盘占用的第一入口。

三、参数逐项实测

3.1 run 参数组

$ docker run hello-world(最小运行验证)

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
退出码=0

$ docker run -d --name web1 ubuntu:22.04 sleep infinity(后台常驻)
be300a9af9e1a8edac07cbf3350480de783e48aa160180eb9a0dd7810b2b3ca2
退出码=0

$ docker run --name web2 --rm ubuntu:22.04 echo "rm demo"(--rm 运行完自动删除)
rm demo
退出码=0

$ docker run -e FOO=bar --name web3 ubuntu:22.04 sh -c "echo FOO=\$FOO"(注入环境变量)
FOO=bar
退出码=0

$ docker run --name web4 -w /tmp ubuntu:22.04 pwd(指定工作目录)
/tmp
退出码=0

$ docker run --name web5 --hostname myhost ubuntu:22.04 hostname(指定主机名)
myhost
退出码=0

$ docker run --name web6 --entrypoint /bin/echo ubuntu:22.04 "entrypoint override"(覆盖入口点)
entrypoint override
退出码=0

$ docker run --name web7 --restart=on-failure:2 ubuntu:22.04 true(重启策略)
退出码=0
参数作用实测表现
-d后台运行并返回完整容器 ID输出 64 位十六进制 ID
--name指定容器名,省略则随机(如 elated_colden)docker ps NAMES 列可见
--rm进程退出即自动删除容器docker ps -a 无残留
-e K=V注入环境变量FOO=bar 回显
-w指定工作目录pwd 输出 /tmp
--hostname指定容器主机名hostname 输出 myhost
--entrypoint覆盖镜像入口点CMD 降级为参数传入
--restart=on-failure:N退出码非 0 时最多重启 N 次true 正常退出不触发

3.2 ps 参数组

$ docker ps
CONTAINER ID   IMAGE          COMMAND            CREATED         STATUS         PORTS     NAMES
be300a9af9e1   ubuntu:22.04   "sleep infinity"   4 seconds ago   Up 3 seconds             web1
退出码=0

$ docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Command}}"
NAMES           STATUS                              COMMAND
web7            Exited (0) Less than a second ago   "true"
web6            Exited (0) Less than a second ago   "/bin/echo 'entrypoi…"
web5            Exited (0) 1 second ago             "hostname"
web4            Exited (0) 1 second ago             "pwd"
web3            Exited (0) 2 seconds ago            "sh -c 'echo FOO=$FO…"
web1            Up 3 seconds                        "sleep infinity"
elated_colden   Exited (0) 3 seconds ago            "/hello"
退出码=0

$ docker ps -q
be300a9af9e1
退出码=0

$ docker ps -a -q | wc -l
7
退出码=0

$ docker ps -n 2 --format "{{.Names}}"
web7
web6
退出码=0

$ docker ps -a --filter name=web --format "{{.Names}}"
web7
web6
web5
web4
web3
web1
退出码=0

$ docker ps -a --filter status=exited --format "{{.Names}}"
web7
web6
web5
web4
web3
elated_colden
退出码=0

$ docker ps --no-trunc --filter name=web1 --format "{{.ID}}"
be300a9af9e1a8edac07cbf3350480de783e48aa160180eb9a0dd7810b2b3ca2
退出码=0

要点:默认只显示运行中容器,-a 补全全部状态;CONTAINER ID 默认截断 12 位,--no-trunc 展示完整;--filter 支持 name、status、label、ancestor 等键;--format 的 Go 模板是脚本化取值的首选。

3.3 images 参数组

$ docker images
WARNING: This output is designed for human readability. For machine-readable output, please use --format.
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
hello-world:latest   e2ac70e7319a       10.1kB             0B   U
ubuntu:22.04         e8df6c74f650       78.1MB             0B   U
退出码=0

$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"
REPOSITORY    TAG       IMAGE ID       SIZE
ubuntu        22.04     e8df6c74f650   78.1MB
hello-world   latest    e2ac70e7319a   10.1kB
退出码=0

$ docker images -q
e8df6c74f650
e2ac70e7319a
退出码=0

$ docker images --digests hello-world
REPOSITORY    TAG       DIGEST                                                                    IMAGE ID       CREATED        SIZE
hello-world   latest    sha256:11a3eb1597e864c51b3f56733cb2e8a90bf0c284bfc05f9444d81c558bc848aa   e2ac70e7319a   6 months ago   10.1kB
退出码=0

$ docker images --no-trunc hello-world --format "{{.ID}}"
sha256:e2ac70e7319a02c5a477f5825259bd118b94e8b02c279c67afa63adab6d8685b
退出码=0

注意:29.x 的 docker images 默认表格新增了 DISK USAGE/CONTENT SIZE/EXTRA 列并输出 WARNING 提示改用 --format——旧脚本若按列号解析需适配。

$ docker pull hello-world(重复 pull 幂等)
docker.io/library/hello-world:latest
退出码=0

$ docker tag ubuntu:22.04 myrepo/ubuntu:demo(打新标签)
退出码=0

$ docker images myrepo/ubuntu
IMAGE                ID             DISK USAGE   CONTENT SIZE   EXTRA
myrepo/ubuntu:demo   e8df6c74f650       78.1MB             0B   U
退出码=0

$ docker rmi myrepo/ubuntu:demo(删除标签)
Untagged: myrepo/ubuntu:demo
退出码=0

$ docker rmi 000000000000(不存在镜像的报错)
Error response from daemon: No such image: 000000000000:latest
退出码=1

$ docker image prune -f(清理悬空镜像)
Total reclaimed space: 0B
退出码=0

$ docker search alpine(搜索镜像,节选)
NAME                DESCRIPTION                                     STARS     OFFICIAL
alpine              A minimal Docker image based on Alpine Linux…   11563     [OK]
alpine/git          A  simple git container running in alpine li…   252
退出码=0

要点:tag 只新增指针不复制层数据;rmi 删的是「标签 + 无引用时的层数据」,同 ID 多标签时只 Untagged;删除不存在的镜像报 daemon 错误且退出码 1。

3.5 inspect 与 history

$ docker inspect ubuntu:22.04 --format "{{.Id}} {{.Architecture}} {{.Os}}"
sha256:e8df6c74f650ad385efe2e20103eca9b0ad50690fb3c63d49fa00762412bbf55 amd64 linux
退出码=0

$ docker inspect ubuntu:22.04 --format "{{.Config.Cmd}}"
[/bin/bash]
退出码=0

$ docker history hello-world
IMAGE          CREATED        CREATED BY                SIZE      COMMENT
e2ac70e7319a   6 months ago   CMD ["/hello"]            0B        buildkit.dockerfile.v0
<missing>      6 months ago   COPY hello / # buildkit   10.1kB    buildkit.dockerfile.v0
退出码=0

$ docker history ubuntu:22.04 | head -5
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
e8df6c74f650   3 weeks ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      3 weeks ago   /bin/sh -c #(nop) ADD file:b0bf3f64519bf10a5…   78.1MB
<missing>      3 weeks ago   /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      3 weeks ago   /bin/sh -c #(nop)  ARG LAUNCHPAD_BUILD_ARCH     0B
退出码=0

inspect 输出 JSON 元数据,--format 配合 Go 模板精确取字段(.State.Status、.HostConfig.Privileged、.NetworkSettings.IPAddress 等);history 逐层展示构建指令与每层体积,<missing> 表示该层已被中间镜像合并共享。

3.6 exec 参数组

$ docker run -d --name app1 ubuntu:22.04 sleep infinity
614c0007168ef9c48628166e1c38b9237b5d8fa01b916761283498087d4ac654
退出码=0

$ docker exec app1 sh -c "echo hello-from-exec"
hello-from-exec
退出码=0

$ docker exec -d app1 sh -c "sleep 30 && echo done > /tmp/bg.txt"(后台 exec)
退出码=0

$ docker exec -e EV=demo -w /var app1 pwd
/var
退出码=0

$ docker exec -u 1000:1000 app1 id(以指定用户执行)
uid=1000 gid=1000 groups=1000
退出码=0

$ docker exec nosuch-container echo hi(exec 不存在的容器)
Error response from daemon: No such container: nosuch-container
退出码=1
参数作用
-d分离模式,命令后台执行不占终端
-e K=V本次 exec 的环境变量
-w本次 exec 的工作目录
-u USER[:GROUP]以指定 UID/GID 执行(实测 uid=1000 gid=1000)

注意:exec 目标容器必须处于 running 状态;容器名不存在时报 No such container,退出码 1。

3.7 logs / top / stats:运行观测

$ docker exec app1 sh -c "echo log-line-1; echo err-line-2 1>&2" && docker logs app1
log-line-1
err-line-2
退出码=0

$ docker logs --tail 1 app1
退出码=0

$ docker logs --timestamps app1
退出码=0

$ docker top app1(容器内进程)
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                5971                5948                0                   03:10               ?                   00:00:00            sleep infinity
root                6035                5948                0                   03:10               ?                   00:00:00            sh -c sleep 30 && echo done > /tmp/bg.txt
root                6041                6035                0                   03:10               ?                   00:00:00            sleep 30
退出码=0

$ docker stats --no-stream app1(资源统计单次)
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O      BLOCK I/O   PIDS
614c0007168e   app1      0.00%     0B / 0B             0.00%     646B / 84B   0B / 0B     3
退出码=0

⚠️ 重要实测结论:docker logs 只收集容器主进程(PID 1)的 stdout/stderr。3.7 第一段里 log-line-1/err-line-2 是 exec 命令自身的输出;随后 docker logs --tail 1 与 --timestamps 均为空——因为主进程是 sleep infinity,无任何输出。exec 的回显不会进入 logs,要持久化 exec 输出需自行落盘或重定向。

3.8 pause / unpause / rename / restart / stop / start / kill

$ docker pause app1
app1
退出码=0

$ docker inspect app1 --format "{{.State.Status}}"(暂停态)
paused
退出码=0

$ docker unpause app1
app1
退出码=0

$ docker inspect app1 --format "{{.State.Status}}"(恢复运行)
running
退出码=0

$ docker rename app1 app2
退出码=0

$ docker ps --filter name=app2 --format "{{.Names}}"
app2
退出码=0

$ docker restart app2
app2
退出码=0

$ docker stop app2
app2
退出码=0

$ docker inspect app2 --format "{{.State.Status}}"
exited
退出码=0

$ docker start app2
app2
退出码=0

$ docker ps --filter name=app2 --format "{{.Status}}"
Up Less than a second
退出码=0

$ docker kill app2
app2
退出码=0

$ docker inspect app2 --format "{{.State.Status}}"
exited
退出码=0

状态机:running ↔ paused(pause 发 SIGSTOP 冻结进程,unpause 恢复);running → exited(stop 优雅终止发 SIGTERM 再 SIGKILL,kill 直接 SIGKILL);exited → running(start 重启原容器,数据与文件系统保留)。rename 在运行中也可执行。

3.9 cp / diff / commit:容器快照

$ docker cp /etc/hostname app2:/tmp/copied.txt(宿文件进容器)
退出码=0

$ docker exec app2 cat /tmp/copied.txt
993b4a0b5ea0
退出码=0

$ docker exec app2 sh -c "echo back > /tmp/out.txt" && docker cp app2:/tmp/out.txt /tmp/from-container.txt && cat /tmp/from-container.txt(容器文件出容器)
back
退出码=0

$ docker diff app2(文件系统改动)
C /tmp
A /tmp/copied.txt
A /tmp/out.txt
退出码=0

$ docker commit app2 app2-snapshot:v1(提交容器为镜像)
sha256:5207ce17749f4c5449da8cfab7f306d7cb34090034fbb2a9b94bd9e420b05c63
退出码=0

$ docker run --rm app2-snapshot:v1 cat /tmp/copied.txt(快照镜像含改动)
993b4a0b5ea0
退出码=0

docker diff 输出三类标记:A 新增(Added)、C 修改(Changed)、D 删除(Deleted)。commit 把容器当前可写层固化为新镜像,快照镜像运行后可直接读到 cp 进去的文件——验证了改动确已固化。

3.10 export / import / rm

$ docker export app2 -o /tmp/app2.tar && ls -lh /tmp/app2.tar(导出文件系统)
-rw------- 1 root root 77M Oct 17 03:10 /tmp/app2.tar
退出码=0

$ docker import /tmp/app2.tar app2-imported:v1
sha256:601ac9ef3eebc3596dd42e070344cbe6f903b9ab91ec2270e5eb9d3819516547
退出码=0

$ docker rm app2
app2
退出码=0

$ docker rm nosuch(删除不存在的容器)
Error response from daemon: No such container: nosuch
退出码=1

$ docker ps -a --format "{{.Names}}"(app2 已删)
退出码=0

export 打平容器文件系统为 tar(不含分层历史与元数据),与 save(完整镜像含分层,3.5 的 /tmp/ubuntu.tar 77M)是两套用途:迁移环境用 export/import,分发镜像用 save/load。运行中的容器删除需 rm -f。

3.11 network:网络全套

$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
bc91cac86c35   bridge    bridge    local
e8c2249cbae2   host      host      local
81e05dd130c6   none      null      local
退出码=0

$ docker network create appnet
d9a245d33053963eb5e396a6f93dfd4d4bfba24eb9cdeb0b0d3575bcd619425c
退出码=0

$ docker network inspect appnet --format "{{.Name}} {{.Driver}} {{.Scope}}"
appnet bridge local
退出码=0

$ docker network inspect bridge --format "{{range .IPAM.Config}}{{.Subnet}}{{end}}"
172.18.0.0/16
退出码=0

$ docker run -d --name n1 --network appnet ubuntu:22.04 sleep infinity
be077741b43b8244cce5164b3ceced81fd14bf16c0860c4519cb7ccee05ca81d
退出码=0

$ docker run -d --name n2 ubuntu:22.04 sleep infinity(默认 bridge)
d07ca0b7f19ef208c09bbae5044b795b44f5eb3ef01f9c620d91cbb13e754c42
退出码=0

$ docker network connect appnet n2(把 n2 接入 appnet)
退出码=0

$ docker exec n2 sh -c "getent hosts n1"(同网络容器名互解析)
172.19.0.2      n1
退出码=0

$ docker network disconnect appnet n2
退出码=0

$ docker network disconnect appnet n1 && docker network rm appnet(有容器接入时不能删,先断开)
appnet
退出码=0

要点:内置三网络 bridge/host/none;自定义网络提供内嵌 DNS——同网络内可直接用容器名互访(实测 getent hosts n1 解析到 172.19.0.2)。默认 bridge 不提供容器名解析(这是自定义网络存在的核心意义)。删除网络前须断开全部接入容器;connect/disconnect 支持运行中容器热插拔。

3.12 volume:数据卷与 bind 挂载

$ docker volume create datavol
datavol
退出码=0

$ docker volume inspect datavol --format "{{.Name}} {{.Mountpoint}} {{.Driver}}"
datavol /var/lib/docker/volumes/datavol/_data local
退出码=0

$ docker run --rm -v datavol:/data ubuntu:22.04 sh -c "echo persisted > /data/file.txt && cat /data/file.txt"(挂卷写入)
persisted
退出码=0

$ docker run --rm -v datavol:/data ubuntu:22.04 cat /data/file.txt(新容器读同一卷)
persisted
退出码=0

$ docker run --rm -v /tmp/hostshare:/mnt/bind ubuntu:22.04 sh -c "echo bind > /mnt/bind/b.txt && cat /mnt/bind/b.txt"(bind 挂载)
bind
退出码=0

$ docker volume rm datavol(卷被占用时报错演示)
Error response from daemon: remove datavol: volume is in use - [80365877dae2...]
退出码=1

$ docker rm -f voluser && docker volume rm datavol
datavol
退出码=0

-v 两种形态:卷名:/容器路径(named volume,由 Docker 管理,实测跨容器数据持久)与 宿路径:/容器路径(bind mount,直通宿目录)。卷被容器占用时删除被拒(volume is in use),先删容器再删卷。

3.13 build 与 Dockerfile

测试用 Dockerfile(全部指令本地可构建,无需外网):

FROM ubuntu:22.04
LABEL demo="build-test"
RUN echo built-ok > /opt/built.txt
CMD ["/bin/echo", "from Dockerfile"]
$ docker build -t demo-image:v1 /tmp
 ---> Removed intermediate container cde0a6f89c33
 ---> ca8667b25808
Successfully built ca8667b25808
Successfully tagged demo-image:v1
退出码=0

$ docker run --rm demo-image:v1(默认 CMD)
from Dockerfile
退出码=0

$ docker run --rm demo-image:v1 cat /opt/built.txt(构建层内容)
built-ok
退出码=0

$ docker build -q -t demo-image:v2 /tmp(安静模式只输出镜像 ID)
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
            Install the buildx component to build images with BuildKit:
            https://docs.docker.com/go/buildx/

sha256:ca8667b258083b68215c52c564d9fa94acbbfe36a6ce8664bbd361228fcd7f96
退出码=0

注意:未安装 buildx 插件时 29.x 回退 legacy builder 并输出 DEPRECATED 提示(构建功能不受影响);生产环境建议安装 docker-buildx 使 BuildKit 生效。-q 只回显镜像 ID 便于脚本接续。

3.14 system df -v 与 prune

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          5         1         156.2MB   78.09MB (49%)
Containers      2         2         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B
退出码=0

$ docker system df -v(详细,节选)
Images space usage:

REPOSITORY      TAG       IMAGE ID       CREATED          SIZE      SHARED SIZE   UNIQUE SIZE   CONTAINERS
demo-image      v1        ca8667b25808   2 seconds ago    78.1MB    78.09MB       0B            0
app2-imported   v1        601ac9ef3eeb   46 seconds ago   78.1MB    0B            78.09MB       0
app2-snapshot   v1        5207ce17749f   49 seconds ago   78.1MB    78.09MB       18B           0
ubuntu          22.04     e8df6c74f650   3 weeks ago      78.1MB    78.09MB       0B            2
hello-world     latest    e2ac70e7319a   6 months ago     10.1kB    0B            10.07kB       0
退出码=0

$ docker container prune -f(清理全部停止容器)
Total reclaimed space: 0B
退出码=0

$ docker ps -a
CONTAINER ID   IMAGE          COMMAND            CREATED         STATUS         PORTS     NAMES
d07ca0b7f19e   ubuntu:22.04   "sleep infinity"   8 seconds ago   Up 8 seconds             n2
be077741b43b   ubuntu:22.04   "sleep infinity"   9 seconds ago   Up 8 seconds             n1
退出码=0

df -v 的 SHARED SIZE/UNIQUE SIZE 直观展示分层共享:demo-image 与 ubuntu 共享 78.09MB 基础层,unique 仅差分内容。prune 家族(container prune、image prune、volume prune、system prune)清理停止容器/悬空镜像/未用卷,-f 免交互确认。

四、实战示例

4.1 场景一:前台调试一个隔离环境

docker run -d --name dbg --hostname dbgbox ubuntu:22.04 sleep infinity
docker exec -it dbg bash          # 交互式进入(本例验证用 -w/-u/-e 参数均可叠加)
docker exec dbg cat /etc/os-release
docker top dbg                    # 观察容器进程树
docker diff dbg                   # 退出前看改了哪些文件
docker rm -f dbg                  # 用完即删

对应 3.1/3.6/3.7/3.9 实测回显;-it 分配 TTY 进入交互 shell,是日常调试最常用组合。

4.2 场景二:固化一个配置好的环境为镜像

docker run -d --name builder ubuntu:22.04 sleep infinity
docker cp ./app.conf builder:/etc/app/app.conf     # 灌入配置
docker exec builder sh -c 'echo ok > /etc/app/ready'
docker diff builder                                 # 确认改动清单
docker commit builder myenv:v1                      # 固化为镜像
docker rm -f builder
docker run --rm myenv:v1 cat /etc/app/ready         # 验证快照可复现

对应 3.9/3.10 实测:commit 产出的镜像运行后可直接读到 cp 进去的文件。长期复用建议改写为 Dockerfile 走 build(3.13),commit 只适合临时快照。

五、注意事项与常见问题

  1. logs 只收主进程:docker exec 的输出不进 docker logs(3.7 实测 logs 为空佐证);排查 exec 命令要去容器里看文件或重新前台执行。
  2. 基础镜像精简:ubuntu:22.04 无 ping 等工具,docker exec n2 ping n1 报 exec: "ping": executable file not found in $PATH,退出码 127;测连通改用 getent hosts 或在镜像里安装 iputils-ping。
  3. 目标不存在一律非零退出:exec/rm 不存在的容器与 rmi 不存在的镜像分别实测退出码 1,错误前缀 Error response from daemon:,脚本判断退出码即可。
  4. volume 占用保护:卷被任何容器(含停止态)引用时 docker volume rm 报 volume is in use(3.12 实测),先 docker rm -f 再删卷。
  5. 网络删除前置:有容器接入的自定义网络不能删,先逐个 disconnect(3.11 实测)。
  6. legacy builder 弃用提示:未装 buildx 时 docker build 输出 DEPRECATED 警告但功能正常(3.13 实测);正式流水线安装 buildx 切 BuildKit。
  7. 嵌套/受限环境用 vfs:宿存储驱动不支持时 overlay 挂载报 invalid argument(实测),dockerd --storage-driver=vfs 可稳定运行,代价是无层共享、磁盘占用偏大。
  8. 资源限制依赖 cgroup 委派:在 cgroupv2 threaded 模式的受限环境里 --memory/--cpus 会报 unable to apply cgroup configuration ... in threaded mode(实测退出码 125);普通宿主机不受影响。
  9. --rm 与 -d 互斥:--rm 在容器退出后立即删除,配合 -d 时注意日志转存;容器名冲突(Conflict. The container name ... is already in use)需先删旧容器。
  10. images 默认表格已变:29.x 新增 DISK USAGE/CONTENT SIZE 列并打印 WARNING(3.3 实测),按列解析的旧脚本请改用 --format。
  11. stop vs kill:stop 给 10 秒优雅退出窗口,kill 立即 SIGKILL;数据库类进程务必用 stop。
  12. cp 支持双向与通配:docker cp 容器:路径 宿路径 与反向均可,目录用 -a 保留属主。

六、参考链接