Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions apps/api/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Build stage
FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./
COPY apps/api/package*.json ./apps/api/
COPY libs/engine/package*.json ./libs/engine/
COPY packages/rules/package*.json ./packages/rules/

# Install dependencies
RUN npm ci

# Copy source code
COPY . .

# Build the API
RUN npm run build --workspace=apps/api

# Production stage
FROM node:18-alpine

RUN apk add --no-cache tini

WORKDIR /app

# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001

# Copy package files and installed node_modules
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
COPY --from=builder --chown=nodejs:nodejs /app/apps/api/package*.json ./apps/api/
COPY --from=builder --chown=nodejs:nodejs /app/libs/engine/package*.json ./libs/engine/
COPY --from=builder --chown=nodejs:nodejs /app/packages/rules/package*.json ./packages/rules/
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules

# Copy built application
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist

# Set environment
ENV NODE_ENV=production
ENV PORT=3000

# Expose port
EXPOSE 3000

# Switch to non-root user
USER nodejs

# Use tini as init process
ENTRYPOINT ["/sbin/tini", "--"]

# Start the API
CMD ["node", "dist/apps/api/main.js"]
165 changes: 165 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
version: "3.8"

services:
# PostgreSQL Database
postgres:
image: postgres:15-alpine
container_name: gasguard-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_USER:-gasguard}
POSTGRES_PASSWORD: ${DB_PASSWORD:-gasguard123}
POSTGRES_DB: ${DB_NAME:-gasguard}
POSTGRES_HOST_AUTH_METHOD: scram-sha-256
volumes:
- postgres-data:/var/lib/postgresql/data
- ./docker/postgres/init:/docker-entrypoint-initdb.d
ports:
- "5432:5432"
networks:
- gasguard-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-gasguard}"]
interval: 10s
timeout: 5s
retries: 5
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

# Redis for BullMQ
redis:
image: redis:7-alpine
container_name: gasguard-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-redis123}
volumes:
- redis-data:/data
ports:
- "6379:6379"
networks:
- gasguard-network
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 5s
retries: 5
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

# Backend API
api:
build:
context: .
dockerfile: apps/api/Dockerfile
container_name: gasguard-api
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
NODE_ENV: ${NODE_ENV:-production}
PORT: 3000
DATABASE_URL: postgresql://${DB_USER:-gasguard}:${DB_PASSWORD:-gasguard123}@postgres:5432/${DB_NAME:-gasguard}
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123}
RATE_LIMIT_TTL: ${RATE_LIMIT_TTL:-60}
RATE_LIMIT_MAX: ${RATE_LIMIT_MAX:-10}
API_VERSION: v1
JWT_SECRET: ${JWT_SECRET:-your-secret-key-change-in-production}
ports:
- "3000:3000"
networks:
- gasguard-network
volumes:
- ./logs:/app/logs
healthcheck:
test:
[
"CMD",
"wget",
"--no-verbose",
"--tries=1",
"--spider",
"http://localhost:3000/health",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

# Worker Service (BullMQ)
worker:
build:
context: .
dockerfile: apps/worker/Dockerfile
container_name: gasguard-worker
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
NODE_ENV: ${NODE_ENV:-production}
DATABASE_URL: postgresql://${DB_USER:-gasguard}:${DB_PASSWORD:-gasguard123}@postgres:5432/${DB_NAME:-gasguard}
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123}
WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-5}
networks:
- gasguard-network
volumes:
- ./logs:/app/logs
deploy:
replicas: ${WORKER_REPLICAS:-2}
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

# Dashboard (Optional)
dashboard:
build:
context: .
dockerfile: apps/dashboard/Dockerfile
container_name: gasguard-dashboard
restart: unless-stopped
depends_on:
- api
environment:
API_URL: http://api:3000
ports:
- "8080:80"
networks:
- gasguard-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

networks:
gasguard-network:
driver: bridge
name: gasguard-network

volumes:
postgres-data:
name: gasguard-postgres-data
redis-data:
name: gasguard-redis-data
Loading