Files
opsxsql/docker-compose.yml
T
Logan.Li 0b16488029 feat(deploy): single-image docker-compose and kubernetes install.sh
- multi-stage root Dockerfile (opsx-loki pattern): frontend dist +
  go binary + gh-ost in one alpine image, non-root user, HEALTHCHECK,
  entrypoint warning for missing SECRET_KEY; gin now serves the SPA
  from DIST_DIR (asset/db-logos/favicon passthrough, /api returns JSON
  404, SPA fallback to index.html) - one origin, no CORS surface
- docker-compose.yml rewritten: single service, named data volume,
  no-new-privileges + cap_drop ALL, /health healthcheck, resource
  limits, log rotation; SECRET_KEY required (openssl rand -hex 32),
  JWT_SECRET optional (auto-generated and persisted in prod)
- kubernetes/: install.sh one-command deploy (idempotent secret
  reuse, --nodeport/--ingress flags, rollout wait, backup tips) plus
  namespace/secret/pvc/deployment(single replica + Recreate, probes,
  resource limits, non-root)/service/nodeport/ingress manifests and
  README (sqlite single-writer constraints, snapshot backup)
- docs: README quick-start now has 3 deployment paths; ARCHITECTURE
  ch.14 expanded

single-image runtime verified locally (SPA/assets/api/login coexist
on :9002); full image build left to server (docker hub unreachable
from this machine)
2026-10-26 20:33:26 +08:00

70 lines
1.9 KiB
YAML

# ============================================================
# opsxsql - Docker Compose 部署(单镜像,参照 opsx-loki)
# 安全基线: 非 root / no-new-privileges / 健康检查 / 资源限额 / 日志轮转
# 使用:
# export SECRET_KEY=$(openssl rand -hex 32)
# export JWT_SECRET=$(openssl rand -hex 32) # 可选;不设则生产模式自动生成并持久化
# docker compose up -d --build
# 访问: http://localhost:9000 (前后端同源,无需单独的前端容器)
# ============================================================
services:
opsxsql:
build:
context: .
dockerfile: Dockerfile
args:
TARGETARCH: ${TARGETARCH:-amd64}
image: opsxsql:latest
container_name: opsxsql
hostname: opsxsql
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
ports:
- "${OPSXSQL_PORT:-9000}:9000"
volumes:
- opsxsql-data:/app/data
environment:
- PORT=9000
- DB_PATH=/app/data/sqlite3.db
- DEBUG=${DEBUG:-false}
# AES 密钥(实例/LDAP 密码加密): 必须外部提供,且部署后不可更换
- "SECRET_KEY=${SECRET_KEY:?SECRET_KEY is required. Generate: openssl rand -hex 32}"
# JWT 密钥: 可选;生产模式未提供时自动生成随机密钥并持久化到数据卷
- JWT_SECRET=${JWT_SECRET:-}
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.25'
memory: 128M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
restart: unless-stopped
stop_grace_period: 15s
volumes:
opsxsql-data:
driver: local