-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.dev.yml
More file actions
171 lines (167 loc) · 6.46 KB
/
docker-compose.dev.yml
File metadata and controls
171 lines (167 loc) · 6.46 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# Boot order (enforced by depends_on + healthchecks):
# 1. postgres — database must be accepting connections
# 2. hasura — GraphQL engine starts after schema exists
# 3. api + front — start in parallel once hasura is healthy
# Ports:
# 5432 → postgres (connect with any SQL client)
# 8080 → hasura (GraphQL endpoint + console UI)
# 8081 → api (Go REST API)
# 5173 → front (Vite dev server with HMR)
services:
postgres:
image: postgres:18-alpine
container_name: operafix_postgres
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-operafix}
POSTGRES_USER: ${POSTGRES_USER:-operafix}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-operafix_dev_password}
volumes:
- postgres_data:/var/lib/postgresql
# init-postgres.sql runs ONCE on first boot (when the volume is empty)
# it enables PostgreSQL extensions that require superuser privileges:
# pgcrypto → gen_random_uuid() used by every table's PK default
# pg_trgm → fast fuzzy search on equipment names and issue titles
# btree_gist → exclusion constraints for PM schedule overlap prevention
- ./scripts/init-postgres.sql:/docker-entrypoint-initdb.d/00-init.sql:ro
ports:
- "5432:5432"
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${POSTGRES_USER:-operafix} -d ${POSTGRES_DB:-operafix}",
]
interval: 5s
timeout: 5s
retries: 10
networks:
- operafix_net
hasura:
build:
context: ./hasura
dockerfile: Dockerfile
target: development
container_name: operafix_hasura
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
# >- is YAML block scalar: joins lines into one string without newline
# to avoid line breaks inside the URL
HASURA_GRAPHQL_DATABASE_URL: >-
postgres://${POSTGRES_USER:-operafix}:${POSTGRES_PASSWORD:-operafix_dev_password}@postgres:5432/${POSTGRES_DB:-operafix}
# TODO: change the secrets hehe
HASURA_GRAPHQL_ADMIN_SECRET: ${HASURA_ADMIN_SECRET:-pNZxIfzAD43hka0HrR02JAmsZmLU10bI}
HASURA_GRAPHQL_JWT_SECRET: >-
{"type":"HS256","key":"${JWT_SECRET:-kK2DUgOa2HZJseW1YpbpTnx1nN2nzOsC4Ar3ZVZc4H3xQLwA0e1nwU5sCeXERwbO}"}
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
HASURA_GRAPHQL_DEV_MODE: "true"
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup,http-log,webhook-log,websocket-log,query-log
HASURA_GRAPHQL_METADATA_DIR: /hasura-metadata
HASURA_GRAPHQL_MIGRATIONS_DIR: /hasura-migrations
# when a DB event fires or an action is invoked, Hasura POSTs to:
# http://api:8080/<handler-path>
# "api" resolves to the Go API container on the Docker network
ACTION_BASE_URL: ${ACTION_BASE_URL:-http://api:8080}
# max simultaneous postgres connections hasura will hold open
HASURA_GRAPHQL_PG_CONNECTIONS: "10"
HASURA_GRAPHQL_TX_ISOLATION: serializable
volumes:
- ./hasura/metadata:/hasura-metadata:ro
- ./hasura/migrations:/hasura-migrations:ro
ports:
- "8080:8080"
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080/healthz || exit 1"]
interval: 10s
timeout: 5s
retries: 15
# give Hasura 20s to start before the first health check fires
# it needs time to connect to Postgres and apply metadata
start_period: 20s
networks:
- operafix_net
api:
build:
context: ./api
dockerfile: Dockerfile
# runs `air` for hot-reload
target: development
container_name: operafix_api
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
hasura:
# go API must start after Hasura is ready
condition: service_healthy
environment:
DATABASE_URL: >-
postgres://${POSTGRES_USER:-operafix}:${POSTGRES_PASSWORD:-operafix_dev_password}@postgres:5432/${POSTGRES_DB:-operafix}?sslmode=disable
# hasura internal endpoint for privileged GraphQL queries
HASURA_ENDPOINT: http://hasura:8080/v1/graphql
HASURA_ADMIN_SECRET: ${HASURA_ADMIN_SECRET:-pNZxIfzAD43hka0HrR02JAmsZmLU10bI}
# JWT signing key, must be identical to Hasura's JWT secret above
JWT_SECRET: ${JWT_SECRET:-kK2DUgOa2HZJseW1YpbpTnx1nN2nzOsC4Ar3ZVZc4H3xQLwA0e1nwU5sCeXERwbO}
# short-lived, rotate via refresh
JWT_ACCESS_EXPIRY: ${JWT_ACCESS_EXPIRY:-15m}
# 7 days, stored in HttpOnly cookie
JWT_REFRESH_EXPIRY: ${JWT_REFRESH_EXPIRY:-168h}
APP_ENV: development
LOG_LEVEL: debug
PORT: 8080
# # External services — leave blank locally unless actively testing
# # that feature. The Go service skips sending when these are empty.
# POSTMARK_API_KEY: ${POSTMARK_API_KEY:-}
# POSTMARK_FROM: ${POSTMARK_FROM:-noreply@localhost}
# TWILIO_ACCOUNT_SID: ${TWILIO_ACCOUNT_SID:-}
# TWILIO_AUTH_TOKEN: ${TWILIO_AUTH_TOKEN:-}
# TWILIO_FROM_NUMBER: ${TWILIO_FROM_NUMBER:-}
# R2_ACCOUNT_ID: ${R2_ACCOUNT_ID:-}
# R2_ACCESS_KEY: ${R2_ACCESS_KEY:-}
# R2_SECRET_KEY: ${R2_SECRET_KEY:-}
# R2_BUCKET: ${R2_BUCKET:-operafix-media}
# R2_PUBLIC_URL: ${R2_PUBLIC_URL:-http://localhost:9000}
volumes:
# mount api/ source into the container so `air` detects file changes
# :delegated, on macOS, relaxes mount consistency for better performance
- ./api:/app:delegated
# avoids re-downloading all dependencies on every `docker compose build`
- go_mod_cache:/root/go/pkg/mod
ports:
- "8081:8080"
networks:
- operafix_net
front:
build:
context: ./front
dockerfile: Dockerfile
target: development
container_name: operafix_front
restart: unless-stopped
depends_on:
hasura:
condition: service_healthy
environment:
# VITE_* prefix is mandatory, vite only injects variables with this
VITE_GRAPHQL_URL: ${VITE_GRAPHQL_URL:-http://localhost:8080/v1/graphql}
VITE_GRAPHQL_WS: ${VITE_GRAPHQL_WS:-ws://localhost:8080/v1/graphql}
# go API base URL
VITE_API_URL: ${VITE_API_URL:-http://localhost:8081}
volumes:
# mount front/ source so Vite's file watcher picks up changes
- ./front:/app:delegated
- front_node_modules:/app/node_modules
ports:
- "5173:5173"
networks:
- operafix_net
volumes:
postgres_data:
go_mod_cache:
front_node_modules:
networks:
operafix_net:
driver: bridge