《Java 编程实战》16.2 容器化:多阶段 Dockerfile 与 Jib
fat jar 解决了依赖问题,但目标机器仍然需要 JRE、正确的用户和健康检查。本节用多阶段 Dockerfile 把 libraryd 装进非 root 镜像,再用 Jib 3.5.2 在不依赖 Docker daemon 的情况下构建,并给出 352 MB 镜像的真实运行结果。
tag
fat jar 解决了依赖问题,但目标机器仍然需要 JRE、正确的用户和健康检查。本节用多阶段 Dockerfile 把 libraryd 装进非 root 镜像,再用 Jib 3.5.2 在不依赖 Docker daemon 的情况下构建,并给出 352 MB 镜像的真实运行结果。
把 TaskAPI 打成最小 Docker 镜像:写多阶段 Dockerfile,构建阶段用 golang:1.27-alpine 编译静态二进制、运行阶段用 alpine 只装产物,配 .dockerignore 与层缓存,用非 root 用户运行,并实测镜像体积、容器日志与端点响应。
系统讲解 Testcontainers 集成测试:容器化测试的原理与 Ryuk 资源回收、GenericContainer 与专用模块(数据库/Kafka/Redis)、@Testcontainers 生命周期与单例复用、等待策略、Docker Compose 模块、Spring Boot @ServiceConnection 零配置注入,以及 CI 环境与并行测试实践。
容器网络故障往往横跨命名空间、veth 对、iptables 与 DNS 四层。本篇给出一套可复用的排障路径:用 nsenter 与 netshoot 进入目标命名空间、按 veth 索引定位对端、检查 DOCKER-USER 与 DNAT 规则、排查 127.0.0.11 内嵌解析器、定位 MTU 分片与 conntrack 表满,并附常见故障模式对照表与排障 SOP。
在流水线里构建镜像有 DinD、DooD 与无守护进程构建器三条路。本篇讲清 docker:dind 的 privileged 与 TLS 配置、storage driver 在嵌套场景下的坑、挂载 docker.sock 的风险边界,给出 GitLab Runner docker executor 与临时 runner 的落地配置、层缓存复用策略与安全加固清单。
macOS 上没有原生容器,必须在轻量虚拟机里跑 Docker。本篇对比 Docker Desktop、Colima 与 OrbStack 三条路线的架构差异,给出 Colima 的 profile 与虚拟机参数配置、OrbStack 的文件共享与内置 K8s 能力、两者的启动速度与挂载性能差异,以及 docker context 切换、团队统一与回退的实践。
系统梳理 Docker 日志的两条路径:日志驱动直发与落盘后采集。逐个对比 json-file、local、journald、fluentd 等驱动的适用场景与配置参数,剖析 max-size/max-file 轮转、非阻塞模式与背压丢日志的机制,并给出采集管道、多行日志处理与容器日志排障的完整实践。
讲解 docker buildx bake 如何用一个声明式文件替代一长串 docker buildx build 命令:HCL/JSON/Compose 三种文件格式与解析优先级、targets/groups/inherits/matrix 语法、变量与上下文注入、多平台与缓存导出配置,以及在 CI 中按需构建、按目标复用的工程实践与调试技巧。
从 daemon 与 daemonless 的架构差异出发,对比 Docker 与 Podman 的进程模型、rootless 默认行为、命令行兼容层、Compose 与 systemd/Quadlet 集成、镜像与 registry 互通性,并给出可回退的迁移路径、常见坑位清单与混合共存策略,帮助团队判断该不该迁、怎么迁、迁完如何验证。
系统讲解生信可复现性与容器化:从可复现性的三个层次、版本锁定四要素、Docker 与 Singularity 容器化、Conda 环境管理、参考数据与索引的版本化,到参数文件与配置管理、数据溯源与元数据、工作流引擎的可复现支持,以及审计与共享实践,给出可落地的工程方案。
系统讲解 BEAM 应用的容器化部署:Mix release 构建与产物结构、多阶段 Dockerfile 与镜像瘦身、runtime.exs 与 RELEASE_* 运行时配置、节点命名与 EPMD 陷阱、libcluster 的 K8s DNS 与 gossip 策略,以及滚动升级、优雅停机和健康检查。
把 TaskHub 的镜像构建从 30.2 秒压到 14.3 秒:把 go.mod 与源码分成两层,改一行代码不再重下全部依赖,实测依赖层命中后构建耗时减半;同时讲清 Go 交叉编译与多架构镜像的差别,以及 buildx 缺失时该如何降级。
把 TaskHub 打成容器镜像:单阶段朴素写法产出 510MB,改用多阶段构建 + CGO_ENABLED=0 静态链接 + distroless 基础镜像后压到 15MB,最终镜像里只剩一个二进制文件,连 shell 都没有,攻击面同步缩小。
从单阶段 Dockerfile 的 1.67GB 讲到多阶段构建的 259MB:实测 builder/runtime 分离、.dockerignore、层缓存重建耗时、非 root 用户、PYTHONUNBUFFERED 与 HEALTHCHECK,并给出镜像瘦身的真实数字与取舍。
从 Linux CFS 调度器与 cgroup v1/v2 CPU 控制器出发,讲解 Docker 的 --cpus、--cpuset-cpus、--cpuset-mems 参数语义与换算,剖析 CPU 节流根因与排查,深入 SCHED_FIFO 实时策略与 RT 带宽,结合 NUMA 拓扑讲解绑核与绑内存节点的远端访问代价,并给出 K8s CPU Manager 对比与生产清单。
从可部署产物到生产运维,系统梳理 Scala 应用的云原生落地路径:sbt-assembly 与 sbt-native-packager 打包、GraalVM native image 与分层镜像、多阶段 Dockerfile 与 jlink 裁剪、JVM 容器感知参数、Kubernetes 清单与 HPA/PDB/拓扑分布、三类探针语义与 SIGTERM 优雅停机、外部化配置与 Secret、结构化日志与 Prometheus/OpenTelemetry 可观测性、滚动更新与金丝雀发布,以及 OOMKilled、CPU throttling 等生产故障排查与成本优化。
围绕 dockerd 进程模型与 docker.service 单元,拆解 Type=notify、Delegate、KillMode、LimitNOFILE 与 TasksMax 语义,讲 docker.socket 按需激活、daemon.json 常用项与校验、drop-in 覆盖与配置优先级、热重载边界,覆盖日志驱动选型与膨胀治理、journald 排障、内核参数、存储 GC 与安全加固。
系统剖析 OCI Image Spec 与 Artifacts 规范:manifest、config、layers 三大组件与 media type、image index 与多架构、artifactType 与 referrers API,把 Helm chart、SBOM、签名作为 OCI 工件推送,并覆盖 OCI layout 与 registry 兼容性差异。
从 BuildKit 内容寻址的缓存模型出发,讲解 cache key 与指令摘要生成规则、cache 挂载持久化依赖目录,深入 cache-from 与 cache-to 的 registry、local、gha 后端写法与参数,剖析 CI 多 job 缓存复用与缓存失效根因(COPY 顺序、apt 元数据、时间戳、ARG 变更),并给出 buildx du 清理与命中率诊断。
从 HEALTHCHECK 的四个时间参数讲到 Compose 的 healthcheck 覆盖、starting/healthy/unhealthy 状态机、四种 restart policy 与退出码语义,再到崩溃循环的指数退避、depends_on 的 service_healthy 依赖编排,以及 compose、Swarm、systemd 三层自愈映射,附生产清单与踩坑表。