Docker 运行时治理:资源限制、健康检查与日志边界
容器能启动不等于服务可长期运行。生产治理至少要覆盖资源上限、进程退出、健康状态、日志轮转、数据持久化和网络暴露。多数线上事故不是 Docker 本身复杂,而是默认值没有被明确设计。
给资源设置边界
内存无限制时,一个异常容器可能挤压整台主机;限制过紧则会频繁 OOM。先根据压测设置初值,再监控峰值:
services:
api:
mem_limit: 1g
cpus: 1.5
pids_limit: 300
应用自身也要感知限制,例如 Go 设置合理 GOMEMLIMIT,JVM 使用容器感知的堆比例。容器内存不仅是语言堆,还包括线程栈、Direct Buffer、页缓存和运行时开销。
Healthcheck 检查“能否服务”
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz >/dev/null || exit 1"]
interval: 10s
timeout: 3s
retries: 5
start_period: 20s
Liveness 只判断进程是否需要重启,Readiness 判断是否能接流量。若把所有下游故障都视为 Liveness 失败,数据库短暂抖动可能导致所有 API 同时重启,放大事故。健康接口要快、无副作用,并设置严格超时。
正确处理 PID 1 与退出信号
容器主进程必须接收 SIGTERM,停止新请求,等待在途任务并在宽限期内退出。Shell 入口脚本应使用 exec 把信号交给应用:
#!/bin/sh
exec /app/server "$@"
需要回收子进程时使用 init: true 或合适 Init。不要依赖 SIGKILL,强杀会中断事务、文件写入和消息确认。
日志必须轮转
直接使用默认 JSON 日志而不限制大小,最终可能写满磁盘:
logging:
driver: json-file
options:
max-size: 20m
max-file: "3"
应用写结构化日志到 stdout/stderr,采集系统负责汇总。容器内不要再维护一套无限增长日志文件。错误日志要包含请求 ID 和业务上下文,但不得打印 Token、验证码和密码。
数据和网络边界
- 数据库、上传文件映射到明确持久卷,并定期备份。
- 只有入口服务映射宿主机端口,内部服务留在私有网络。
- 配置文件只读挂载,运行目录按最小权限开放。
- 不挂载 Docker Socket 给普通业务容器。
- 使用固定服务名发现,不把临时容器 IP 写入配置。
发布前演练
重启容器、重启 Docker、磁盘接近满、下游不可用、进程收到 SIGTERM、数据卷迁移、日志快速增长,这些场景都应有预期行为。能从故障中恢复,才算完成部署。

评论
0 条讨论