安全加固与端口收敛
部署完成后最重要的一步:确保业务端口不直接暴露公网,只有 Traefik 的 80/443(和 SSH)对外。
收敛原则
| 端口 | 用途 | 是否公网 |
|---|---|---|
| 80 / 443 | Traefik 入口 | ✅ 开放 |
| 122 | SSH | ✅ 开放 |
| 3000 / 8080 | 前端 / 后端 | ❌ 仅本机 |
| 3306 / 6379 | MySQL / Redis | ❌ 仅本机 |
| 6443 / 10250 | K3s 系统 | ❌ 仅内网 |
访问关系:公网 → 80/443 → Traefik → 内部服务,业务端口不直接对外。
1. 端口绑定 127.0.0.1
docker-compose 中把端口从 0.0.0.0 改绑到 127.0.0.1:
yaml
services:
frontend:
ports:
- "127.0.0.1:3000:3000" # 之前是 "3000:3000"(等价 0.0.0.0)
backend:
ports:
- "127.0.0.1:8080:8080"
mysql:
ports:
- "127.0.0.1:3306:3306"
redis:
ports:
- "127.0.0.1:6379:6379"为什么服务还能访问
Traefik 是通过桥接网络 IP(如 172.19.0.3:3000)访问容器,与宿主端口映射无关。改绑 127.0.0.1 不影响路由,只阻止公网直连。
2. 固定容器 IP
Docker 容器重建后 IP 可能变化,导致 K8s Endpoints 指向失效。在 compose 中固定:
yaml
services:
frontend:
networks:
home:
ipv4_address: 172.19.0.3
networks:
home:
name: ljdou-home_default
external: true # 引用已存在的网络固定后,K8s Endpoints 与容器 IP 长期一致,不再担心 502。
3. 健康检查
depends_on 默认只等容器「启动」而非「就绪」。MySQL 启动需要时间,后端可能抢跑导致连接失败。给依赖加健康检查:
yaml
services:
mysql:
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot123"]
interval: 5s
timeout: 5s
retries: 20
redis:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
backend:
depends_on:
mysql:
condition: service_healthy # 等 MySQL 就绪再启动
redis:
condition: service_healthy4. 验证
bash
# 容器状态应显示 (healthy)
docker ps
# 确认业务端口不再监听 0.0.0.0
ss -tlnp | grep -E '0.0.0.0:(3000|8080|3306|6379)' || echo "已收敛"
# 确认后端数据库连接正常
docker logs ljdou-backend | grep -i mysql最终防护建议
即使宿主机端口已收敛,仍建议在云安全组层面只放行 80 / 443 / 122,形成双层防护:
公网 → 云安全组(80/443/122) → 服务器防火墙 → Traefik → 服务宿主机上宝塔面板(14639)、宝塔 MySQL(13306)、Traefik 仪表盘(18080)等端口,如无必要也应一并收敛。