
本地 `docker compose up -d` 一把梭很爽。但同一份配置直接放到公网服务器上,常见的结果是第一天一切正常,第三十天出问题:磁盘被日志写满、容器崩了没人拉起来、数据库端口裸奔在公网上。
下面是我每次部署前会过一遍的清单,针对「单台 VPS 跑几个服务」这个最常见的场景。
## 镜像版本写死,别用 latest
`image: nginx:latest` 意味着你下一次 `docker compose pull` 拿到的可能是另一个版本,而且你不会提前知道。生产环境一律写具体版本号——升级应该是主动行为,不是意外。
```yaml
services:
web:
image: nginx:1.27.4 # 好
# image: nginx:latest # 坏
```
## 给每个服务配 restart 策略
容器崩溃或宿主机重启后,没有重启策略的服务就躺在那儿了。
```yaml
restart: unless-stopped
```
`unless-stopped` 与 `always` 的区别:手动 `docker stop` 之后,前者不会在守护进程重启时把容器又拉起来。日常用前者更符合直觉。
## 数据库要等它真的就绪
`depends_on` 默认只等容器「启动」,不等服务「可用」。应用启动时数据库还在初始化,连不上就退出,然后无限重启。加上健康检查才是真等:
```yaml
services:
app:
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
retries: 5
```
## 数据必须放卷里
容器的可写层是临时的,容器一删数据就没了。数据库、上传的文件、配置文件,一律用命名卷:
```yaml
volumes:
db_data:
services:
db:
volumes:
- db_data:/var/lib/postgresql/data
```
顺带一句:**卷不等于备份**。卷只解决「容器重建不丢数据」,硬盘挂了照样没。该做的备份还是得做。
## 限制日志体积
默认的 json-file 日志驱动会一直写,直到把磁盘填满——这是小 VPS 上最常见的猝死方式。
```yaml
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
```
## 只发布需要暴露的端口
这是最容易出事的一条。Docker 会自己写 iptables 规则,一个 `5432:5432` 很可能绕开你配好的 UFW 直接暴露到公网。数据库和缓存根本不需要发布端口,它们在 compose 的内部网络里就能互通。
Web 服务绑到回环地址,让反代去收口:
```yaml
ports:
- "127.0.0.1:3000:3000"
```
## 用反代统一收口 80/443
只让 Nginx / Caddy / Traefik 监听 80 和 443。TLS 终止、证书续期、路由都在这一层做,之后要加压缩、限流、安全头也只有一个地方要改。
## 密钥别写进镜像和 Git
密码、API Key 放 `.env` 并加进 `.gitignore`,或者用 compose secrets 从文件读:
```yaml
services:
db:
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
```
## 给容易爆内存的服务加资源限制
```yaml
deploy:
resources:
limits:
memory: 512M
cpus: "1.0"
```
## 最后:定期看一眼磁盘
```bash
docker system df # 看镜像、容器、卷分别占多少
docker system prune -a # 清理无用镜像和构建缓存(执行前确认没有要保留的)
```
## 小结
这份清单不复杂,但每一条对应的都是真实会发生的故障:版本漂移、崩溃不恢复、数据丢失、磁盘写满、端口裸奔。部署前花十分钟过一遍,能省掉后面好几个半夜的排查。
后面会写 Docker + Nginx 反代 + 证书自动续期的完整部署流程,把这篇里没展开的部分补上。
原创
Docker Compose 上生产前,我会过一遍的清单
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法