
译者按:自托管虽爽,但安全责任也随之而来。本文整理了 8 个常见的 Docker Compose 安全错误,看看你踩过几个。
自托管的好处很明显:数据更可控、避免厂商锁定、深入理解技术栈。但代价是——那些「无聊但重要」的事也得自己来:端口暴露、容器默认配置、密钥管理、备份、更新、反向代理、数据库安全。
很多 Homelab 一开始都是这么写的:
services:
app:
image: myapp:latest
ports:
- "8080:8080"
db:
image: postgres:latest
ports:
- "5432:5432"
能用,看起来也没问题。但一个能跑的 Docker Compose 文件,不等于一个安全的配置。
数据库通常不需要暴露到公网。把 PostgreSQL(5432)、MySQL(3306)、Redis(6379)、MongoDB(27017)直接暴露出去风险很大。
更安全的做法:完全不映射端口,只让同 Docker 网络内的其他容器访问。如果真的需要本地访问,绑定到 localhost 而不是所有接口:127.0.0.1:5432:5432。
privileged: true 会给容器超出常规的系统权限。大多数服务其实不需要这个。在启用前,问自己:这真的必需吗?有没有更细粒度的 capability 方案?镜像可信吗?服务公开暴露吗?
主机网络模式移除了 Docker 的网络隔离,增加了端口暴露的复杂性。使用前确认:服务真的需要吗?开了哪些端口?在反向代理后面吗?普通 Docker 网络不能满足需求吗?
很多镜像默认以 root 运行。如果可能,指定非 root 用户:user: "1000:1000"。虽然有些服务需要特殊配置,但如果可以,通常值得考虑。
这很方便,也很容易忘记。硬编码的密钥可能出现在 Git 历史、共享代码、截图、公有仓库里。更好的方案:使用 .env 文件(注意不要提交)、Docker secrets、或者密钥管理服务。
latest 不是版本号,是移动靶。对于数据库这类有状态服务尤其危险——更新是不可控的。固定版本号(postgres:16.2、redis:7.2.4),让更新变成有意的操作。
有持久化卷就应该有备份。好的备份计划要回答:备份什么?存哪?多久一次?加密了吗?测试过恢复吗?谁知道怎么恢复?
记住:没测试过恢复的备份不是真正的备份。
Traefik、Caddy、Nginx Proxy Manager 这些工具很有用,但也可能让暴露变得更难理解。关键问题不是「有没有反向代理」,而是「我是否清楚哪些服务可从哪访问、为什么可访问?」
暴露 Homelab 服务前,快速检查:
privileged: true 的容器吗?network_mode: host 的服务吗?自托管给了你控制权,但控制权意味着责任。这些检查不能替代完整的安全审计,但能帮你发现很多容易忽略的问题。
原文链接