because I got bored of customising my CV for every job
1services:
2 caddy:
3 image: caddy:2-alpine
4 environment:
5 DOMAIN: ${DOMAIN}
6 BASIC_AUTH_USER: ${BASIC_AUTH_USER:-admin}
7 BASIC_AUTH_HASH: ${BASIC_AUTH_HASH}
8 ports:
9 - "80:80"
10 - "443:443"
11 volumes:
12 - ./ci/Caddyfile:/etc/caddy/Caddyfile:ro
13 - caddy-data:/data
14 - caddy-config:/config
15 depends_on:
16 server:
17 condition: service_healthy
18 client:
19 condition: service_healthy
20 restart: unless-stopped
21
22 db:
23 image: postgres:16-alpine
24 environment:
25 POSTGRES_USER: ${POSTGRES_USER}
26 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
27 POSTGRES_DB: ${POSTGRES_DB}
28 volumes:
29 - db-data:/var/lib/postgresql/data
30 healthcheck:
31 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
32 interval: 10s
33 timeout: 5s
34 retries: 3
35 restart: unless-stopped
36
37 server:
38 build:
39 context: .
40 dockerfile: .docker/server.Dockerfile
41 target: production
42 additional_contexts:
43 project-q: ${PROJECT_Q_PATH}
44 nest-service-locator: ${NEST_SERVICE_LOCATOR_PATH}
45 environment:
46 PORT: "3000"
47 NODE_ENV: production
48 DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
49 JWT_SECRET: ${JWT_SECRET}
50 JWT_ACCESS_TOKEN_EXPIRY: ${JWT_ACCESS_TOKEN_EXPIRY:-15m}
51 JWT_REFRESH_TOKEN_EXPIRY: ${JWT_REFRESH_TOKEN_EXPIRY:-7d}
52 ENCRYPTION_KEY: ${ENCRYPTION_KEY}
53 RESEND_API_KEY: ${RESEND_API_KEY:-}
54 EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-}
55 EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-CV Generator}
56 CLIENT_URL: ${PUBLIC_URL}
57 ALLOWED_ORIGINS: ${PUBLIC_URL}
58 AI_PROVIDER: ${AI_PROVIDER:-anthropic}
59 AI_TEMPERATURE: ${AI_TEMPERATURE:-0.1}
60 AI_MAX_TOKENS: ${AI_MAX_TOKENS:-8192}
61 AI_TIMEOUT: ${AI_TIMEOUT:-60000}
62 ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
63 ANTHROPIC_MODEL: ${ANTHROPIC_MODEL:-claude-sonnet-4-5-20250929}
64 OPENAI_API_KEY: ${OPENAI_API_KEY:-}
65 OPENAI_MODEL: ${OPENAI_MODEL:-gpt-4o-mini}
66 PDF_OUTPUT_DIR: /app/pdf-output
67 depends_on:
68 db:
69 condition: service_healthy
70 volumes:
71 - worker-output:/app/pdf-output:ro
72 healthcheck:
73 test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
74 interval: 15s
75 timeout: 5s
76 retries: 3
77 start_period: 30s
78 restart: unless-stopped
79
80 client:
81 build:
82 context: .
83 dockerfile: .docker/client.Dockerfile
84 target: production
85 args:
86 VITE_SERVER_URL: ${PUBLIC_URL}
87 VITE_DOCS_URL: https://docs.${DOMAIN}
88 healthcheck:
89 test: ["CMD", "curl", "-f", "http://localhost:80"]
90 interval: 15s
91 timeout: 5s
92 retries: 3
93 start_period: 5s
94 restart: unless-stopped
95
96 worker:
97 build:
98 context: .
99 dockerfile: .docker/worker.Dockerfile
100 target: production
101 additional_contexts:
102 project-q: ${PROJECT_Q_PATH}
103 nest-service-locator: ${NEST_SERVICE_LOCATOR_PATH}
104 environment:
105 DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
106 QUEUE_SCHEMA: ${QUEUE_SCHEMA:-queue}
107 QUEUE_NAME: ${QUEUE_NAME:-default}
108 POLL_INTERVAL_MS: ${POLL_INTERVAL_MS:-2000}
109 PDF_OUTPUT_DIR: /app/pdf-output
110 PDF_TIMEOUT_MS: ${PDF_TIMEOUT_MS:-30000}
111 HEARTBEAT_FILE_PATH: /tmp/worker-heartbeat
112 HEARTBEAT_DB_INTERVAL_MS: ${HEARTBEAT_DB_INTERVAL_MS:-30000}
113 CHROMIUM_ARGS: ${CHROMIUM_ARGS:---no-sandbox,--disable-dev-shm-usage,--disable-gpu,--single-process,--disable-extensions}
114 depends_on:
115 db:
116 condition: service_healthy
117 volumes:
118 - worker-output:/app/pdf-output
119 deploy:
120 resources:
121 limits:
122 memory: 512M
123 healthcheck:
124 test: ["CMD-SHELL", "find /tmp/worker-heartbeat -mmin -1 | grep -q ."]
125 interval: 30s
126 timeout: 5s
127 retries: 3
128 start_period: 15s
129 restart: unless-stopped
130
131 docs:
132 profiles:
133 - docs
134 build:
135 context: .
136 dockerfile: .docker/docs.Dockerfile
137 target: production
138 args:
139 VITE_CLIENT_URL: ${PUBLIC_URL}
140 VITE_SERVER_URL: ${PUBLIC_URL}
141 healthcheck:
142 test: ["CMD", "curl", "-f", "http://localhost:80"]
143 interval: 15s
144 timeout: 5s
145 retries: 3
146 start_period: 5s
147 restart: unless-stopped
148
149volumes:
150 db-data:
151 worker-output:
152 caddy-data:
153 caddy-config: