在 Docker Engine 29.8.2 里实测 docker cp:src 与 src/. 的区别、目标目录不存在的几种结果、属主(macOS 上拷进去仍是 501:20)、拷到 tmpfs 时退出码 0 但文件丢失、-L 对符号链接的影响,以及 64 MiB 文件拷进 799 ms、拷出 513 ms(中位数,3 次的波动不小)。
在 Docker Engine 29.8.2 里实测容器的状态机:created(Pid=0、没有 IP)→ running → paused → exited(stop -t 1 后 ExitCode 137)→ 再 start 可写层仍在;docker run --rm 的事件是 create → attach → start → die → destroy,docker stop 会先后发出信号 15 和 9;一次 docker run --rm true 约 243 ms。
进入 Docker Desktop 虚拟机实测容器进程的父进程链:容器里的 PID 1 在虚拟机里是 13063,它的父进程是 containerd-shim-runc-v2(-id 等于容器 ID),shim 的父进程是 /initd(PID 1);每个容器一个 shim,容器运行时没有 runc 进程;docker exec 的进程挂在同一个 shim 下;kill -9 主进程后容器 exited(137),shim 随之消失。
在 Docker Engine 29.8.2 里逐个复现容器退出码:127(命令不存在)、126(不可执行)、125(docker 自己出错)、128 加信号编号(TERM 143、INT 130、ABRT 134、SEGV 139、KILL 137);PID 1 没处理程序时 docker stop 得到 137 而 --init 得到 143;137 要靠 OOMKilled 区分 OOM 与 kill。
在 Docker Engine 29.8.2 里实测重启策略:no 不重启、on-failure:2 只在失败时重启 2 次、always 和 unless-stopped 连成功退出也重启;失败容器的重启间隔 175、276、467、886、1679、3310、6537 ms,每次约翻倍;docker stop 和 docker kill 之后不会被拉起;--rm 与 --restart 冲突。
在 Docker Engine 29.8.2 里实测停止信号与宽限期:docker stop 默认发 SIGTERM,--stop-signal 和 Dockerfile 的 STOPSIGNAL 可以换信号且运行时优先;清理要 3 秒的程序 -t 5 能干净退出(0)、-t 1 被打断(137);这台 Docker Desktop 的守护进程默认宽限期是 3 秒(default-stop-timeout),--stop-timeout 与 docker stop -t 依次覆盖它。
在 Docker Engine 29.8.2 里实测僵尸进程:不 wait 的 PID 1 留下 50 个僵尸;--init 只能收孤儿(孤儿 50 个 → 0 个僵尸),父进程还活着时僵尸照旧 50 个;僵尸占着进程号,--pids-limit 40 下 39 个僵尸后创建子进程失败;docker top 看不到僵尸,容器里的 ps 才看得到。
在 Docker Engine 29.8.2 里实测 --init:PID 1 变成 /sbin/docker-init(tini 0.19.0,601296 字节,VmRSS 508 kB,运行时从虚拟机只读挂载进容器,不在镜像里),你的程序是 PID 7;子进程的退出码(3、137、143)原样穿过;能自己处理信号的程序有没有 init 都收到 SIGUSR1;启动开销中位数 175 ms 对 170 ms,在抖动范围内。
在 Docker Engine 29.8.2 里实测 --ulimit:默认 nofile 是 1048576、nproc 无限制;nofile=64 时只能再打开 61 个文件(扣掉 0/1/2);soft 不能超过 hard、普通用户的 hard 只能降不能升;nproc 按用户 uid 在系统范围内统计,两个同 uid 容器占掉 14 个进程后,新容器 nproc=20 只能再建 5 个。
在 Docker Engine 29.8.2(cgroup v2)里实测 CPU 限制:--cpus 0.5/1/2 让满负荷的容器平均只占 0.50/1.00/2.02 个 CPU(cpu.max 的配额/周期),--cpu-quota 25000 是 0.25;--cpu-shares 没有竞争时不限制(shares 2 仍用满 2.00 个 CPU),同一 CPU 上争抢时按权重分,1024 对 512 约 1.57:1,shares 被换算成非线性的 cpu.weight(512 → 59、1024 → 100、2048 → 174)。
在 Docker Engine 29.8.2 里实测 CPU 节流对延迟的影响:30 ms 的任务在 --cpus 0.5 下 p50 从 30.0 变成 71.7 ms(累计被节流 2622 ms),周期改成 10 ms 后变成 56.3 ms;5 ms 的短任务 p50 不变但 p95 到 17.4 ms;4 进程并行 160 ms CPU 的任务在 --cpus 1 下最慢 188 ms(不限制 67 ms),全部被节流。
在 Docker Engine 29.8.2(cgroup v2)里实测 --memory 与 --memory-swap:只给 --memory 64m 时 swap 也被限在 64 MiB(memory.swap.max=67108864),--memory-swap 是内存加 swap 的总和;分配 200 MiB 时,不允许 swap 的容器在 50 MiB 被杀,允许 64 MiB swap 的在 110 MiB 被杀,swap 不限的 200 MiB 全部分配完(151 MiB 在 swap 里);--memory-reservation 对应 memory.low。