# ============================================================================= # MeshSafe 单机部署(内网光闸摆渡场景) # ============================================================================= # # 启动顺序: # 1) 准备 .env(cp .env.example .env 并填 MESHSAFE_MASTER_KEY) # 2) 准备数据目录(mkdir -p data/{postgres,redis,clamav,logs,temp}) # 3) docker compose up -d postgres redis # 先起基础设施 # 4) docker compose up -d clamav # ClamAV(如首次启动尝试 freshclam 拉签名库) # 5) bash scripts/import_clamav_db.sh clamav-db-*.tar.gz # 光闸摆渡导入签名库(可选) # 6) docker compose up -d --build api # 起主服务 # 7) docker compose exec api python scripts/init_db.py # 建表 + admin + 初始策略 # 8) docker compose up -d nginx # 最后起 Nginx # # 外部访问:http://<内网服务器IP>:44380/console/login # ============================================================================= services: # ---------- PostgreSQL ---------- postgres: image: postgres:16-alpine container_name: meshsafe-postgres restart: unless-stopped networks: [meshsafe_net] environment: - TZ=Asia/Shanghai - POSTGRES_DB=meshsafe - POSTGRES_USER=meshsafe - POSTGRES_PASSWORD=${MESHSAFE_DB_PASSWORD:-meshsafe} volumes: - ./data/postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U meshsafe -d meshsafe"] interval: 10s timeout: 3s retries: 5 # ---------- Redis ---------- redis: image: redis:7-alpine container_name: meshsafe-redis restart: unless-stopped networks: [meshsafe_net] environment: - TZ=Asia/Shanghai command: ["redis-server", "--maxmemory", "128mb", "--maxmemory-policy", "allkeys-lru"] volumes: - ./data/redis:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 # ---------- ClamAV ---------- # 生产:签名库通过光闸离线同步 # 外网 → bash scripts/sync_clamav_db.sh 生成 clamav-db-*.tar.gz # 光闸摆渡 → bash scripts/import_clamav_db.sh clamav-db-*.tar.gz(放 ./data/clamav 下) # 首次启动脚本(scripts/init_clamav.sh):如 ./data/clamav 为空则尝试 freshclam clamav: image: clamav/clamav:latest container_name: meshsafe-clamav restart: unless-stopped networks: [meshsafe_net] environment: - TZ=Asia/Shanghai volumes: - ./data/clamav:/var/lib/clamav - ./scripts/init_clamav.sh:/init_clamav.sh:ro - ./data/clamav/clamd.conf:/etc/clamav/clamd.conf:ro entrypoint: ["/init_clamav.sh"] healthcheck: test: ["CMD-SHELL", "echo PING | nc -w 2 localhost 3310 || exit 1"] interval: 60s timeout: 5s start_period: 180s retries: 5 # ---------- API 主服务 ---------- api: build: context: . dockerfile: Dockerfile image: meshsafe:latest container_name: meshsafe-api restart: unless-stopped networks: [meshsafe_net] depends_on: postgres: condition: service_healthy redis: condition: service_healthy clamav: condition: service_started environment: - TZ=Asia/Shanghai - MESHSAFE_ENV=prod - MESHSAFE_HOST=0.0.0.0 - MESHSAFE_PORT=8443 - MESHSAFE_LOG_LEVEL=INFO - MESHSAFE_DB_URL=postgresql+psycopg2://meshsafe:${MESHSAFE_DB_PASSWORD:-meshsafe}@postgres:5432/meshsafe - MESHSAFE_MASTER_KEY=${MESHSAFE_MASTER_KEY:?MASTER_KEY_REQUIRED} - MESHSAFE_ADMIN_PASSWORD=${MESHSAFE_ADMIN_PASSWORD:-admin123} - MESHSAFE_POLICY_FILE=/app/config/policy.yaml - MESHSAFE_CLAMAV_HOST=clamav # API 调用方白名单:client_id:client_secret,client_id2:client_secret2 # ⚠️ 生产环境必须替换为真实密钥,切勿把生产密钥提交到仓库 - MESHSAFE_API_CLIENTS=${MESHSAFE_API_CLIENTS:-test-client:test-secret} - MESHSAFE_CLAMAV_PORT=3310 - MESHSAFE_REDIS_URL=redis://redis:6379/0 - MESHSAFE_WORKERS=2 - MESHSAFE_RULES_DIR=/app/rules # uvicorn / DB 连接池(并发优化) - UVICORN_WORKERS=${UVICORN_WORKERS:-8} - DB_POOL_SIZE=${DB_POOL_SIZE:-30} - DB_MAX_OVERFLOW=${DB_MAX_OVERFLOW:-50} volumes: - ./data/logs:/var/log/meshsafe - ./data/temp:/tmp/meshsafe - ./rules:/app/rules:ro - ./config/policy.yaml:/app/config/policy.yaml:ro - ./config/diagnostics.yaml:/app/config/diagnostics.yaml:ro - ./data/clamav:/var/lib/clamav # 共享签名库目录(api 可写入上传的 .cvd 文件,clamd 自动热加载) - /var/run/docker.sock:/var/run/docker.sock:ro # 诊断套件只读访问 Docker(可选;没有也能降级) - ./data/diagnostics:/app/data/diagnostics # 诊断套件持久化(规则历史 + 日志快照) group_add: - "999" # docker.sock 的 GID,让 api 容器能读 healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8443/api/v1/health', timeout=3).read()"] interval: 30s timeout: 5s start_period: 15s retries: 3 # ---------- Nginx(反向代理,内网 HTTP 明文)---------- # 外部端口 44380 → 内部 80 → api:8443 # 无 TLS,外层防护靠光闸 nginx: image: nginx:1.27-alpine container_name: meshsafe-nginx restart: unless-stopped networks: [meshsafe_net] environment: - TZ=Asia/Shanghai depends_on: api: condition: service_healthy ports: - "0.0.0.0:44380:80" volumes: - ./deploy/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro # ---------- 独立 bridge 网络 ---------- # 容器间走服务名通信,IP 由 Docker 自动分配,无需固定网段 networks: meshsafe_net: driver: bridge