SafeLine 雷池:Docker 部署 Web 应用防火墙
本文属于「自托管 Docker 部署实战」系列(共 35 篇),第 4 篇。 示例中的 IP(192.0.2.10)、域名(example.com)、密码均为占位符,请按实际环境替换。
它是什么
SafeLine(雷池)是长亭科技开源的 Web 应用防火墙:把站点流量先经过雷池,由它拦截 SQL 注入、XSS、命令执行、恶意爬虫等攻击,再转发给后端。
它由 7 个容器组成:PostgreSQL、管理端(mgt)、检测引擎(detector)、Tengine 网关、luigi、fvm、chaos(人机验证/动态防护)。
前置条件
- 一台 Linux 服务器(2C4G 起,检测引擎吃内存);
- 已安装 Docker 与 Compose v2;
- 宿主机 80/443 没有被别的 Web 服务占用(Tengine 用 host 网络直接监听)。
curl -fsSL https://get.docker.com | sh
mkdir -p /srv/docker/active/safeline && cd /srv/docker/active/safeline
镜像地址
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-postgres:15.2
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-mgt:latest
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-detector:latest
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-tengine:latest
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-luigi:latest
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-fvm:latest
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-chaos:latest
目录结构
/srv/docker/active/safeline/
├── docker-compose.yml
├── .env
├── resources/ # 各组件的持久化数据
│ ├── postgres/
│ ├── mgt/ detector/ nginx/ chaos/ luigi/ cache/ sock/
└── logs/
部署步骤
cat > .env <<'EOF'
IMAGE_PREFIX=swr.cn-east-3.myhuaweicloud.com/chaitin-safeline
IMAGE_TAG=latest
SUBNET_PREFIX=172.28.0
SAFELINE_DIR=.
MGT_PORT=9443
POSTGRES_PASSWORD=<强密码>
MGT_PROXY=0
RELEASE=
REGION=
ARCH_SUFFIX=
EOF
chmod 600 .env
# docker-compose.yml
networks:
safeline-ce:
name: safeline-ce
driver: bridge
ipam:
driver: default
config:
- gateway: ${SUBNET_PREFIX}.1
subnet: ${SUBNET_PREFIX}.0/24
driver_opts:
com.docker.network.bridge.name: safeline-ce
services:
postgres:
container_name: safeline-pg
restart: always
image: ${IMAGE_PREFIX}/safeline-postgres${ARCH_SUFFIX}:15.2
volumes:
- ${SAFELINE_DIR}/resources/postgres/data:/var/lib/postgresql/data
- /etc/localtime:/etc/localtime:ro
environment:
- POSTGRES_USER=safeline-ce
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.2
command: [postgres, -c, max_connections=600]
healthcheck:
test: pg_isready -U safeline-ce -d safeline-ce
mgt:
container_name: safeline-mgt
restart: always
image: ${IMAGE_PREFIX}/safeline-mgt${REGION}${ARCH_SUFFIX}:${IMAGE_TAG}
volumes:
- /etc/localtime:/etc/localtime:ro
- ${SAFELINE_DIR}/resources/mgt:/app/data
- ${SAFELINE_DIR}/logs/nginx:/app/log/nginx:z
- ${SAFELINE_DIR}/resources/sock:/app/sock
- /var/run:/app/run
ports:
- ${MGT_PORT:-9443}:1443
healthcheck:
test: curl -k -f https://localhost:1443/api/open/health
environment:
- MGT_PG=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable
- MGT_PROXY=${MGT_PROXY}
depends_on:
- postgres
- fvm
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.4
detect:
container_name: safeline-detector
restart: always
image: ${IMAGE_PREFIX}/safeline-detector${REGION}${ARCH_SUFFIX}:${IMAGE_TAG}
volumes:
- ${SAFELINE_DIR}/resources/detector:/resources/detector
- ${SAFELINE_DIR}/logs/detector:/logs/detector
- /etc/localtime:/etc/localtime:ro
environment:
- LOG_DIR=/logs/detector
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.5
tengine:
container_name: safeline-tengine
restart: always
image: ${IMAGE_PREFIX}/safeline-tengine${REGION}${ARCH_SUFFIX}:${IMAGE_TAG}
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/resolv.conf:/etc/resolv.conf:ro
- ${SAFELINE_DIR}/resources/nginx:/etc/nginx
- ${SAFELINE_DIR}/resources/detector:/resources/detector
- ${SAFELINE_DIR}/resources/chaos:/resources/chaos
- ${SAFELINE_DIR}/logs/nginx:/var/log/nginx:z
- ${SAFELINE_DIR}/resources/cache:/usr/local/nginx/cache
- ${SAFELINE_DIR}/resources/sock:/app/sock
environment:
- TCD_MGT_API=https://${SUBNET_PREFIX}.4:1443/api/open/publish/server
- TCD_SNSERVER=${SUBNET_PREFIX}.5:8000
- CHAOS_ADDR=${SUBNET_PREFIX}.10
ulimits:
nofile: 131072
network_mode: host
luigi:
container_name: safeline-luigi
restart: always
image: ${IMAGE_PREFIX}/safeline-luigi${REGION}${ARCH_SUFFIX}:${IMAGE_TAG}
environment:
- MGT_IP=${SUBNET_PREFIX}.4
- LUIGI_PG=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable
volumes:
- /etc/localtime:/etc/localtime:ro
- ${SAFELINE_DIR}/resources/luigi:/app/data
depends_on:
- detect
- mgt
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.7
fvm:
container_name: safeline-fvm
restart: always
image: ${IMAGE_PREFIX}/safeline-fvm${REGION}${ARCH_SUFFIX}:${IMAGE_TAG}
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.8
chaos:
container_name: safeline-chaos
restart: always
image: ${IMAGE_PREFIX}/safeline-chaos${REGION}${ARCH_SUFFIX}:${IMAGE_TAG}
environment:
- DB_ADDR=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-pg/safeline-ce?sslmode=disable
volumes:
- ${SAFELINE_DIR}/resources/sock:/app/sock
- ${SAFELINE_DIR}/resources/chaos:/app/chaos
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.10
docker compose up -d
docker compose ps
管理端:https://<SERVER_IP>:9443(自签证书,浏览器需手动信任)。首次登录按页面提示初始化管理员。
关键配置
| 项 | 说明 |
|---|---|
SUBNET_PREFIX |
内部网段,默认 172.28.0;与已有网段冲突要改 |
MGT_PORT |
管理端端口,默认 9443 |
IMAGE_PREFIX/IMAGE_TAG |
镜像仓库与版本,升级时改 tag |
SAFELINE_DIR |
数据根目录,示例为当前目录 |
tengine |
host 网络,直接占用宿主机 80/443 |
注意事项
- 80/443 冲突:Tengine 用 host 网络,宿主机已有 Nginx/NPM/Caddy 时起不来,先停掉或改端口方案;
- 内部网段
172.28.0.0/24可能与 Docker 默认网段/VPN 冲突,docker network ls先确认; - 雷池的数据都在
resources/,尤其postgres/,升级前必须整目录备份; - 升级跨大版本要按官方发布说明执行,直接
pull latest可能触发数据库迁移失败; - 管理端一定要改默认密码,且只对内网开放,9443 不要直接暴露公网;
- 后端站点接入后,记得把真实域名解析到雷池,而不是绕过它直连后端。
备份与升级
# 停服 → 打包数据 → 起服(保证 postgres 一致性)
docker compose stop
tar czf "safeline-$(date +%F).tar.gz" .env resources
docker compose start
# 升级:改 IMAGE_TAG 或 pull 后重建
docker compose pull
docker compose up -d
docker compose ps
- 升级失败时用备份回滚:恢复
resources/与.env,再把IMAGE_TAG改回旧值。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果