Docker 笔记(一)镜像篇:分层原理、Dockerfile 写法与镜像瘦身
镜像不是单个文件,是一叠只读层。这篇讲清联合文件系统与写时复制、Dockerfile 每条指令分别产生什么代价、构建缓存怎么命中(为什么改一行代码要重装依赖)、多阶段构建怎么把 1.2G 瘦到 120M,以及基础镜像怎么选。
从一个关键词,发现新的思路。
镜像不是单个文件,是一叠只读层。这篇讲清联合文件系统与写时复制、Dockerfile 每条指令分别产生什么代价、构建缓存怎么命中(为什么改一行代码要重装依赖)、多阶段构建怎么把 1.2G 瘦到 120M,以及基础镜像怎么选。
容器不是一个小型虚拟机,它是被 namespace 隔离、被 cgroup 限制的一个进程。理解了这点,「为什么一启动就退出」「为什么 JVM 以为自己有 64G 内存」「为什么 exit 137」都能自己解释。这篇讲生命周期、run 参数、cgroup 限制与 JVM 的关系、退出码速查、优雅停机和健康检查。
容器的「网络不通」和「文件没权限」是运维群里最高频的两类问题,绝大多数不是 Docker 的 bug,而是网络模型与宿主机的差异没搞清。这篇讲四种网络模式、bridge 到底靠什么打通、-p 与 EXPOSE 的区别、容器间怎么互访、localhost 的陷阱,以及 volume/bind mount/tmpfs 怎么选和权限、时区怎么配。
单个容器好管,一堆容器就靠 Compose。但 Compose 里最容易踩的不是语法,是「启动顺序」和「日志把磁盘吃光」。这篇给一份能直接改用的 Java + MySQL + Redis 编排示例,讲清 depends_on 为什么只等启动不等就绪、日志驱动怎么配才不会撑爆根分区,以及上线前必须过一遍的检查清单。
前四篇是按知识点讲的,这篇是反过来用的:命令忘了、线上出事了,回来翻。上半部分按镜像、容器、网络、存储、Compose、系统清理分组整理常用命令,能直接复制;下半部分是 12 个真实场景案例,每个给出现象、怎么查、结论三步。
老 JDK 不识别 cgroup,容器限 2G 却按宿主机 64G 算堆,还按 32 核起线程,结果被 OOMKilled 或越跑越慢。讲清 UseContainerSupport、MaxRAMPercentage、堆外开销、cgroup v1/v2 文件,以及容器里 jstack/jmap 的正确姿势。
容器写挂载目录报 Permission denied,根因常是 UID 不一致,也可能是 SELinux 或只读挂载。顺带整理容器时区不对、构建缓存导致改了代码镜像没更新两个小坑,每条都给出复现现象与 id、ls -ln、docker exec 排查命令。
docker ps 里一个容器永远显示 Restarting,日志什么都没有。docker inspect 看 OOMKilled 与 ExitCode 137,配合 docker events、stats、dmesg 定位内存超限,讲清 restart policy 如何放大故障、-m 与 swap 的关系,附 exit code 速查表。
凌晨磁盘告警,df 显示根分区 100%,罪魁是 /var/lib/docker。用 docker system df -v、du 逐层下钻,定位到 json-file 日志无限增长,讲清 max-size/max-file 配置、docker system prune 各选项的风险(--volumes 会删数据)与构建缓存清理。
容器访问宿主机 MySQL 报 Connection refused,同一 compose 里 localhost 也不通。梳理 host.docker.internal 与 host-gateway、服务名 DNS、-p 与 EXPOSE、默认 bridge 无 DNS、ufw 被 Docker 绕过,附 docker network inspect 与 nsenter 排查命令和网络拓扑图。