本文属于「自托管 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 改回旧值。