Skip to content

Commit 2b9ebfe

Browse files
authored
Merge pull request #78 from Emmanuel-Ugochukwu1/feat/docker-compose
feat(docker): complete full-stack Docker Compose setup (#40)
2 parents b91fbbd + e69747a commit 2b9ebfe

4 files changed

Lines changed: 130 additions & 23 deletions

File tree

docker-compose.yml

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,95 @@
1-
version: '3.8'
1+
# ---------------------------------------------------------------------------
2+
# Veridion full-stack development environment.
3+
#
4+
# docker compose up -d
5+
#
6+
# Starts: PostgreSQL, Redis, API (NestJS), and Web (Next.js).
7+
# The API runs Prisma migrations (`db push`) automatically on startup.
8+
# See `.env.example` for a full reference of available environment variables.
9+
# ---------------------------------------------------------------------------
210

311
services:
412
postgres:
513
image: postgres:16-alpine
614
container_name: veridion-db
715
environment:
8-
POSTGRES_USER: veridion
9-
POSTGRES_PASSWORD: veridion
10-
POSTGRES_DB: veridion
16+
POSTGRES_USER: ${POSTGRES_USER:-veridion}
17+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-veridion}
18+
POSTGRES_DB: ${POSTGRES_DB:-veridion}
1119
ports:
12-
- '5432:5432'
20+
- '${POSTGRES_PORT:-5432}:5432'
1321
volumes:
1422
- postgres_data:/var/lib/postgresql/data
1523
healthcheck:
16-
test: ['CMD-SHELL', 'pg_isready -U veridion']
24+
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-veridion}']
1725
interval: 5s
1826
timeout: 5s
19-
retries: 5
27+
retries: 10
2028

2129
redis:
2230
image: redis:7-alpine
2331
container_name: veridion-redis
2432
ports:
25-
- '6379:6379'
33+
- '${REDIS_PORT:-6379}:6379'
2634
volumes:
2735
- redis_data:/data
2836
healthcheck:
2937
test: ['CMD', 'redis-cli', 'ping']
3038
interval: 5s
3139
timeout: 5s
32-
retries: 5
40+
retries: 10
3341

3442
api:
3543
build:
3644
context: .
3745
dockerfile: docker/Dockerfile.api
3846
container_name: veridion-api
3947
ports:
40-
- '4000:4000'
48+
- '${PORT:-4000}:4000'
4149
environment:
42-
NODE_ENV: development
43-
DATABASE_URL: postgresql://veridion:veridion@postgres:5432/veridion
50+
NODE_ENV: ${NODE_ENV:-development}
51+
PORT: 4000
52+
CORS_ORIGIN: ${CORS_ORIGIN:-http://localhost:3000}
53+
# Database
54+
DATABASE_URL: postgresql://${POSTGRES_USER:-veridion}:${POSTGRES_PASSWORD:-veridion}@postgres:5432/${POSTGRES_DB:-veridion}
55+
# Redis
56+
REDIS_HOST: redis
57+
REDIS_PORT: 6379
4458
REDIS_URL: redis://redis:6379
45-
JWT_SECRET: dev-jwt-secret-change-in-production
46-
JWT_REFRESH_SECRET: dev-refresh-secret-change-in-production
59+
# Auth
60+
JWT_SECRET: ${JWT_SECRET:-dev-secret}
61+
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-dev-refresh-secret}
62+
JWT_EXPIRATION: ${JWT_EXPIRATION:-15m}
63+
JWT_REFRESH_EXPIRATION: ${JWT_REFRESH_EXPIRATION:-7d}
64+
# AI
65+
AI_PROVIDER: ${AI_PROVIDER:-openai}
66+
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
67+
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
68+
# Blockchain
69+
STELLAR_NETWORK: ${STELLAR_NETWORK:-testnet}
70+
STELLAR_RPC_URL: ${STELLAR_RPC_URL:-https://soroban-testnet.stellar.org}
71+
# Email
72+
SMTP_HOST: ${SMTP_HOST:-}
73+
SMTP_PORT: ${SMTP_PORT:-}
74+
SMTP_USER: ${SMTP_USER:-}
75+
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
76+
EMAIL_FROM: ${EMAIL_FROM:-}
4777
depends_on:
4878
postgres:
4979
condition: service_healthy
5080
redis:
5181
condition: service_healthy
52-
volumes:
53-
- .:/app
54-
- /app/node_modules
82+
healthcheck:
83+
test:
84+
[
85+
'CMD-SHELL',
86+
'node -e "fetch(''http://localhost:4000/api/v1/health'').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"',
87+
]
88+
interval: 15s
89+
timeout: 5s
90+
retries: 5
91+
start_period: 30s
92+
restart: unless-stopped
5593

5694
web:
5795
build:
@@ -61,12 +99,24 @@ services:
6199
ports:
62100
- '3000:3000'
63101
environment:
64-
NEXT_PUBLIC_API_URL: http://localhost:4000/api/v1
102+
NODE_ENV: ${NODE_ENV:-development}
103+
NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL:-http://localhost:3000}
104+
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:4000}
105+
NEXT_PUBLIC_STELLAR_NETWORK: ${NEXT_PUBLIC_STELLAR_NETWORK:-testnet}
65106
depends_on:
66-
- api
67-
volumes:
68-
- .:/app
69-
- /app/node_modules
107+
api:
108+
condition: service_healthy
109+
healthcheck:
110+
test:
111+
[
112+
'CMD-SHELL',
113+
'node -e "fetch(''http://localhost:3000'').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"',
114+
]
115+
interval: 15s
116+
timeout: 5s
117+
retries: 5
118+
start_period: 30s
119+
restart: unless-stopped
70120

71121
volumes:
72122
postgres_data:

docker/Dockerfile.api

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ RUN corepack enable && corepack prepare pnpm@9.1.0 --activate
33

44
FROM base AS builder
55
WORKDIR /app
6+
# Use a hoisted (flat) node_modules layout so the runtime image can copy
7+
# node_modules directly without pnpm's nested symlink structure.
8+
ENV npm_config_node_linker=hoisted
69
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json ./
710
COPY packages ./packages
811
COPY apps/api ./apps/api
@@ -11,9 +14,21 @@ RUN pnpm turbo build --filter=@veridion/api
1114

1215
FROM base AS runner
1316
WORKDIR /app
17+
RUN apk add --no-cache openssl
18+
19+
# Copy the built API and its dependencies
1420
COPY --from=builder /app/node_modules ./node_modules
1521
COPY --from=builder /app/apps/api/dist ./apps/api/dist
1622
COPY --from=builder /app/apps/api/package.json ./apps/api/package.json
1723

24+
# Copy all workspace packages (built dist + prisma schema) so the pnpm
25+
# workspace symlinks in node_modules resolve correctly at runtime and
26+
# migrations can run via the database package's Prisma CLI.
27+
COPY --from=builder /app/packages ./packages
28+
29+
# Copy the migration entrypoint
30+
COPY docker/entrypoint.api.sh ./entrypoint.api.sh
31+
RUN chmod +x ./entrypoint.api.sh
32+
1833
EXPOSE 4000
19-
CMD ["node", "apps/api/dist/main.js"]
34+
ENTRYPOINT ["./entrypoint.api.sh"]

docker/Dockerfile.web

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ RUN corepack enable && corepack prepare pnpm@9.1.0 --activate
33

44
FROM base AS builder
55
WORKDIR /app
6+
# Use a hoisted (flat) node_modules layout so the runtime image can copy
7+
# node_modules directly without pnpm's nested symlink structure.
8+
ENV npm_config_node_linker=hoisted
69
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json ./
710
COPY packages ./packages
811
COPY apps/web ./apps/web
@@ -14,7 +17,11 @@ WORKDIR /app
1417
COPY --from=builder /app/apps/web/.next ./apps/web/.next
1518
COPY --from=builder /app/apps/web/public ./apps/web/public
1619
COPY --from=builder /app/apps/web/package.json ./apps/web/package.json
20+
COPY --from=builder /app/apps/web/next.config.js ./apps/web/next.config.js
1721
COPY --from=builder /app/node_modules ./node_modules
22+
# Copy all workspace packages so the pnpm workspace symlinks resolve at runtime.
23+
COPY --from=builder /app/packages ./packages
24+
COPY --from=builder /app/pnpm-workspace.yaml ./pnpm-workspace.yaml
1825

1926
EXPOSE 3000
2027
CMD ["pnpm", "--filter", "@veridion/web", "start"]

docker/entrypoint.api.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/sh
2+
set -e
3+
4+
echo "🚀 Starting Veridion API..."
5+
6+
SCHEMA="${PRISMA_SCHEMA_PATH:-packages/database/prisma/schema.prisma}"
7+
8+
# Locate the Prisma CLI. pnpm nests it under the database package's bin;
9+
# fall back to the root node_modules bin and `npx` as a last resort.
10+
if [ -x "packages/database/node_modules/.bin/prisma" ]; then
11+
PRISMA="packages/database/node_modules/.bin/prisma"
12+
elif [ -x "node_modules/.bin/prisma" ]; then
13+
PRISMA="node_modules/.bin/prisma"
14+
else
15+
PRISMA="npx prisma"
16+
fi
17+
18+
echo "⏳ Applying database schema (using: $PRISMA)..."
19+
20+
attempt=0
21+
max_attempts=30
22+
until $PRISMA db push --schema "$SCHEMA" --skip-generate --accept-data-loss; do
23+
attempt=$((attempt + 1))
24+
if [ "$attempt" -ge "$max_attempts" ]; then
25+
echo "❌ Database not reachable after ${max_attempts} attempts. Exiting."
26+
exit 1
27+
fi
28+
echo "⏳ Database not ready yet (attempt ${attempt}/${max_attempts}) — retrying in 2s..."
29+
sleep 2
30+
done
31+
32+
echo "✅ Database schema is up to date."
33+
34+
# Start the API server.
35+
exec node apps/api/dist/main.js

0 commit comments

Comments
 (0)