init2121212

This commit is contained in:
ZOMBIIIIIII
2026-05-28 14:01:10 +03:00
parent e86ff7c063
commit a636bd573a
3 changed files with 271 additions and 9 deletions

161
docker-compose.yml Normal file
View File

@@ -0,0 +1,161 @@
# ─────────────────────────────────────────────────────────────────────
# Production docker-compose для CryptoWallet API.
#
# Что в этом stack:
# - api — наш Node.js API (multi-stage build из ./Dockerfile)
# - postgres — хранилище encrypted_mnemonic + audit_log
# - keydb — Redis-compatible для idempotency cache + asset map cache
#
# Что НЕ включено (production не использует — оператор настраивает отдельно):
# - Vault — production использует HashiCorp Vault HA cluster (VAULT_ADDR в .env)
# - JWT signer— production принимает JWT от bitok (внешний сервис, JWT_ISSUER в .env)
# - web-ui — фронтенд деплоится отдельно (Vercel / nginx CDN / etc.)
# - vault-init — production Vault уже инициализирован оператором (см. README pre-deploy)
#
# Security hardening:
# - api запускается под uid 1001, read-only fs, cap_drop ALL, no-new-privileges
# - api порт 3001 биндится на 127.0.0.1 (наружу через nginx + TLS, оператор)
# - postgres + keydb без exposed ports (только internal docker network)
# - .env с secrets — 600 permission, не в репо
#
# Usage:
# cp .env.example .env # заполнить все VAULT_*, JWT_*, REDIS_PASSWORD, CORS_ORIGINS, etc.
# chmod 600 .env
# docker compose up -d --build
# docker compose logs -f api
# ─────────────────────────────────────────────────────────────────────
services:
api:
build:
# Context = parent dir (мы внутри deployserver/, апи берёт apps/api/ из родителя)
context: ..
dockerfile: deployserver/Dockerfile
image: cryptowallet-api:latest
container_name: cw-api
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
keydb:
condition: service_healthy
env_file:
- .env
environment:
# Override DB/Redis host для docker network (если в .env стоят prod hosts —
# внутри compose их replace на internal service names)
POSTGRES_HOST: postgres
POSTGRES_PORT: "5432"
REDIS_HOST: keydb
REDIS_PORT: "6379"
ports:
# Loopback only — наружу через nginx reverse proxy + TLS
- "127.0.0.1:3001:3001"
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
deploy:
resources:
limits:
memory: 512M
cpus: "1.0"
pids: 200
reservations:
memory: 256M
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3001/api/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
postgres:
image: postgres:16-alpine
container_name: cw-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:?POSTGRES_USER required}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD required}
POSTGRES_DB: ${POSTGRES_DB:-cryptowallet}
volumes:
- pgdata:/var/lib/postgresql/data
# Bind-mount schema.sql если оператор хочет авто-init на свежей БД.
# На existing — pg ignores 01-schema.sql (initdb запускается только если /var/lib/postgresql/data пуст).
# См. README — лучше прогонять schema руками: psql -f cryptowallet-schema.sql
# - ./cryptowallet-schema.sql:/docker-entrypoint-initdb.d/01-schema.sql:ro
# Internal only — никаких ports на host
expose:
- "5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB:-cryptowallet}"]
interval: 10s
timeout: 3s
retries: 5
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
keydb:
image: eqalpha/keydb:alpine
container_name: cw-keydb
restart: unless-stopped
volumes:
- keydb_data:/data
expose:
- "6379"
command:
- keydb-server
- --requirepass
- "${REDIS_PASSWORD:?REDIS_PASSWORD required}"
- --dir
- /data
- --appendonly
- "yes"
- --appendfsync
- everysec
- --save
- "900"
- "1"
- --save
- "300"
- "10"
- --save
- "60"
- "10000"
- --maxmemory
- "256mb"
- --maxmemory-policy
- "allkeys-lru"
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 3s
retries: 5
deploy:
resources:
limits:
memory: 320M
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
volumes:
pgdata:
keydb_data:
networks:
default:
driver: bridge