资讯文章 资讯 · NEWS
装进容器之后,目录站多出来的那几个坑
2026-10-24 约 1,392 字 预计阅读 3 分钟 yiyunkj
装
容器化的好处不用多说,麻烦在于它把一批原本由系统托管的责任交给了你自己:日志谁切、时间谁定、进程死了谁拉起来。
下面这几条不是最佳实践清单,是几个"跑三个月才发作"的坑。

图片来源:网络,版权归原作者所有,侵权请联系删除
镜像:两阶段构建加非 root
一个目录站的 Node 或 Go 应用,把编译工具链留在生产镜像里,体积能差十倍。两阶段构建的做法是第一阶段用完整镜像编译,第二阶段只把产物和运行时依赖复制过去,基础镜像换成 slim 或 alpine 版本。
顺带三条:.dockerignore 必须写,否则 .git、node_modules、本地日志会进构建上下文,.env 更是可能被打进某一层;镜像标签别用 latest,用语义版本或提交哈希,否则"上次发的到底是哪个版本"这个问题迟早会问;最后加一行 USER 指定非 root 用户,容器逃逸的时候差别很大。
启动命令用 exec 形式(CMD ["node", "server.js"])而不是 shell 形式,这样应用能直接收到 SIGTERM,优雅退出才能生效。
时区:容器默认是 UTC
这是中文站最容易忽略的一条。容器里的系统时间通常是 UTC,而你的业务时间、定时任务、日志时间戳都按东八区理解,于是"每天凌晨两点重建索引"变成了上午十点。
三种改法:在 Dockerfile 里装 tzdata 并设 ENV TZ=Asia/Shanghai;或者把宿主机的 /etc/localtime 和 /etc/timezone 挂进去;也可以在编排文件里直接给环境变量。选一种并在全站统一,别有的容器改有的不改。
更稳的做法是存储层一律存 UTC,只在展示层转,这样容器时区配错了也不会污染数据。
日志:默认驱动会一直写
Docker 默认的 json-file 日志驱动没有上限,容器跑几个月,日志文件能把磁盘占满。目录站里跑着定时任务和队列 worker 的容器尤其容易中招。
两行配置解决:max-size=10m 加 max-file=3,写在服务的 logging 配置里,或者统一写到 /etc/docker/daemon.json 做全局默认。重要的容器再把日志接到能检索的地方,本地只留短期副本。
健康检查:进程活着不等于在服务
这条是容器化之后最反直觉的一点。Docker 只在主进程退出时重启容器,如果应用死锁了——进程还在,但已经不响应请求——容器状态依然是健康的,什么都不会发生。
所以要写 HEALTHCHECK:间隔 30 秒、超时 3 到 10 秒、给一个 30 到 40 秒的启动宽限期、连续失败 3 次判定不健康。健康检查的端点要走真实的内部路径,别只返回一个固定字符串。再配上 restart: unless-stopped,凌晨挂掉的容器能在你被叫醒之前自己回来。
资源、端口和只读根
不给限制的容器会一直吃内存,直到宿主的内核 OOM killer 出手,而它杀谁不由你决定。给每个服务设内存和 CPU 上限,按观测到的峰值再加一半余量。
端口只绑到 127.0.0.1,让反向代理去面对外网,容器本身不直接暴露。文件系统能用只读就只读,需要写的地方挂 tmpfs:访问日志、会话、临时目录,这些都是可再生的。
上传目录和数据库这类必须持久化的,用命名卷,不要写进容器的可写层——容器一删就没了。
容器化没有减少要做的事,只是把"这台机器怎么配"换成了"这个镜像怎么描述"。写进 Dockerfile 的每一条,都是原来那份没人维护的部署文档的替代品。