-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
102 lines (99 loc) Β· 4.48 KB
/
Copy pathdocker-compose.yml
File metadata and controls
102 lines (99 loc) Β· 4.48 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
services:
db:
image: postgres:18-bookworm
restart: unless-stopped
shm_size: '2GB' # Required for REFRESH MATERIALIZED VIEW with
# maintenance_work_mem=2GB. Default Docker
# shm (64MB) causes "No space left on device".
environment:
POSTGRES_DB: gnaf
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}
# C locale is REQUIRED for text_pattern_ops index performance.
# The Tier 0b and Tier 1 indexes use text_pattern_ops for prefix
# matching. Without C locale, they fall back to ICU/UTF-8 which
# adds 10-20% overhead per index comparison.
POSTGRES_INITDB_ARGS: "--locale=C --encoding=UTF8"
# No host port mapping β DB is only reachable via Docker internal network.
# api connects at postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/gnaf.
volumes:
# Postgres 18+ requires the mount at /var/lib/postgresql (not /data).
# The image creates a major-version-specific subdirectory automatically.
- pgdata:/var/lib/postgresql
- ./postgresql.conf:/etc/postgresql/postgresql.conf
# Mount individual SQL files (NOT 005_prewarm.sql β that runs after the
# loader via scripts/load.ts, since the MV must have data first)
- ./sql/001_extensions.sql:/docker-entrypoint-initdb.d/001_extensions.sql
- ./sql/003b_abbrev_map.sql:/docker-entrypoint-initdb.d/003b_abbrev_map.sql
- ./sql/003c_expand_fn.sql:/docker-entrypoint-initdb.d/003c_expand_fn.sql
- ./sql/005_staging.sql:/docker-entrypoint-initdb.d/005_staging.sql
- ./sql/006_staging_indexes.sql:/docker-entrypoint-initdb.d/006_staging_indexes.sql
- ./sql/007_mv.sql:/docker-entrypoint-initdb.d/007_mv.sql
- ./sql/008_api_keys.sql:/docker-entrypoint-initdb.d/008_api_keys.sql
- ./sql/009_domain_verify.sql:/docker-entrypoint-initdb.d/009_domain_verify.sql
- ./sql/010_last_verified.sql:/docker-entrypoint-initdb.d/010_last_verified.sql
- ./sql/011_gnaf_roles.sql:/docker-entrypoint-initdb.d/011_gnaf_roles.sql
- ./sql/012_api_key_expiry.sql:/docker-entrypoint-initdb.d/012_api_key_expiry.sql
command: postgres -c config_file=/etc/postgresql/postgresql.conf
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d gnaf"]
interval: 5s
timeout: 5s
retries: 10
start_period: 30s
deploy:
resources:
limits:
memory: 20G
api:
build: .
restart: unless-stopped
# CD pushes to GHCR; image tag is set by the CD workflow.
# Local `docker compose up` builds from source (build: . takes precedence).
image: ghcr.io/${GH_USER:-lst97}/gnaf-autocomplete:${IMAGE_TAG:-latest}
ports:
- "8000:8000"
env_file: .env
environment:
# Docker-network-specific β overrides whatever DATABASE_URL the .env file sets,
# because within the compose network Postgres is at `db:5432`, not localhost.
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/gnaf
# NODE_ENV=production enables 120/min rate limiting.
# Set via .env for production; omitted locally to keep it disabled.
# NODE_ENV: ${NODE_ENV:-development}
PUBLIC_URL: ${PUBLIC_URL:-} # Same-origin domain mismatch bypass
volumes:
# G-NAF data directory β only needed by the loader, not by the API runtime.
# The CD workflow auto-downloads data here if missing. Mounted rw so
# the loader can create and read PSV files. Defaults to ../gnaf-data
# (parent of the project root) for both local dev and production.
# Override via GNAF_DATA_ROOT env var.
- ${GNAF_DATA_ROOT:-../gnaf-data}:/opt/gnaf-data:rw
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/healthz"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
deploy:
resources:
limits:
# 8GB required for 9-worker parallel COPY during `bun run scripts/load.ts`.
# Runtime API typically uses <500MB; the extra is for the loader which
# runs 9 concurrent COPY FROM STDIN streams for the largest states.
memory: 8G
tunnel:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CF_TUNNEL_TOKEN}
depends_on:
- api
restart: unless-stopped
profiles:
- production
volumes:
pgdata: