Repository navigation
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
115 lines (111 loc) · 4.92 KB
/
Copy pathdocker-compose.yml
File metadata and controls
115 lines (111 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
services:
# ── PostgreSQL 16 ───────────────────────────────────────────────────────────
# Replaced SQL Server in v5. Postgres has no licensing issues, no DB size cap,
# and no per-core licensing. The migrations runner inside the web container
# creates all tables on first startup, so there is no separate init step.
# NOTE: Default credentials are for local development only.
# For networked/production use, override via .env file.
postgres:
image: postgres:16-alpine
# Parallel workers exchange data through /dev/shm. Docker's 64 MB default is
# too small at scale: a parallel VACUUM failed with "could not resize shared
# memory segment ... No space left on device" on a 41M-assignment database, and
# a parallel hash join hits the same limit. A ceiling, not a reservation:
# tmpfs only uses memory for what is actually written.
shm_size: 1gb
restart: unless-stopped
environment:
POSTGRES_DB: "${POSTGRES_DB:-identity_atlas}"
POSTGRES_USER: "${POSTGRES_USER:-identity_atlas}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-identity_atlas_local}"
ports:
# Bind Postgres to loopback only — the dev stack ships a known default
# password, so publishing 5432 on 0.0.0.0 would let anyone on the same
# network reach the database. Local tools (psql, a GUI) still connect via
# localhost:5432; nothing needs it exposed to the LAN.
- "127.0.0.1:5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-identity_atlas} -d ${POSTGRES_DB:-identity_atlas}"]
interval: 10s
timeout: 5s
retries: 30
start_period: 30s
# Same hardening as docker-compose.prod.yml. The official Postgres image
# needs these capabilities to fix data-directory ownership and drop to the
# postgres user.
security_opt:
- no-new-privileges:true
cap_drop: [ALL]
cap_add: [CHOWN, DAC_OVERRIDE, FOWNER, SETGID, SETUID]
pids_limit: 2048
# ── Web (serves built frontend + API) ───────────────────────────────────────
web:
restart: unless-stopped
build:
context: .
dockerfile: app/api/Dockerfile
args:
MODULE_VERSION: "${MODULE_VERSION:-}"
environment:
NODE_ENV: production
USE_SQL: "true" # legacy flag — still used by routes to enable DB-backed mode
DATABASE_URL: "postgres://${POSTGRES_USER:-identity_atlas}:${POSTGRES_PASSWORD:-identity_atlas_local}@postgres:5432/${POSTGRES_DB:-identity_atlas}"
AUTH_ENABLED: "false"
PORT: "3001"
CRAWLER_MANIFESTS_DIR: "/app/crawlers"
# Keep the auto-generated vault master key on the web-only volume, not on
# the job_data volume the worker mounts.
IDENTITY_ATLAS_KEY_DIR: /data/keys
# How many distinct values a filter/attribute dropdown preloads per field
# (default 500, max 5000). Lower it to exercise the "more values than fit
# in the list" path on a small dataset — see docs/architecture/matrix.md.
MATRIX_VALUE_PAGE_SIZE: "${MATRIX_VALUE_PAGE_SIZE:-}"
ports:
- "3001:3001"
volumes:
- job_data:/data/uploads
- web_keys:/data/keys
- ./setup/IdentityAtlas.psd1:/app/setup/IdentityAtlas.psd1:ro
depends_on:
postgres:
condition: service_healthy
security_opt:
- no-new-privileges:true
cap_drop: [ALL]
pids_limit: 2048
# ── Worker (PowerShell — crawlers, risk scoring, account correlation) ──────
# In v5 the worker container has NO database driver. It talks to the API
# for everything (job pickup, ingest, progress reporting).
worker:
build:
context: .
dockerfile: setup/docker/Dockerfile.powershell
args:
MODULE_VERSION: "${MODULE_VERSION:-}"
environment:
# API URL for the worker scheduler. The web container is reachable via
# the docker network DNS name `web` on its internal port.
WEB_API_URL: "http://web:3001/api"
# Optional fixed crawler API key. Leave empty and the worker uses the key
# the web container writes to the shared volume. Crawler and LLM
# credentials are configured in the UI and reach the worker per job.
CRAWLER_API_KEY: "${CRAWLER_API_KEY:-}"
volumes:
- job_data:/data/uploads
depends_on:
# Wait for the API to pass its healthcheck (migrations applied, /api/version
# answering) before the worker starts firing crawler jobs at it — not merely
# for the container to have started.
web:
condition: service_healthy
security_opt:
- no-new-privileges:true
cap_drop: [ALL]
pids_limit: 4096
restart: unless-stopped
volumes:
postgres_data:
job_data:
web_keys: