Files
flyer-crawler.projectium.com/compose.dev.yml
Torben Sorensen d03900cefe
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 19m4s
set PST as common time zone for log matching ease
2026-01-22 23:38:45 -08:00

236 lines
8.7 KiB
YAML

# compose.dev.yml
# ============================================================================
# DEVELOPMENT DOCKER COMPOSE CONFIGURATION
# ============================================================================
# This file defines the local development environment using Docker/Podman.
#
# Services:
# - app: Node.js application (API + Frontend + Bugsink + Logstash)
# - postgres: PostgreSQL 15 with PostGIS extension
# - redis: Redis for caching and job queues
#
# Usage:
# Start all services: podman-compose -f compose.dev.yml up -d
# Stop all services: podman-compose -f compose.dev.yml down
# View logs: podman-compose -f compose.dev.yml logs -f
# Reset everything: podman-compose -f compose.dev.yml down -v
#
# VS Code Dev Containers:
# This file is referenced by .devcontainer/devcontainer.json for seamless
# VS Code integration. Open the project in VS Code and use "Reopen in Container".
#
# Bugsink (ADR-015):
# Access error tracking UI at http://localhost:8000
# Default login: admin@localhost / admin
# ============================================================================
version: '3.8'
services:
# ===================
# Application Service
# ===================
app:
container_name: flyer-crawler-dev
# Use pre-built image if available, otherwise build from Dockerfile.dev
# To build: podman build -f Dockerfile.dev -t flyer-crawler-dev:latest .
image: localhost/flyer-crawler-dev:latest
build:
context: .
dockerfile: Dockerfile.dev
volumes:
# Mount the current directory to /app in the container
- .:/app
# Create a volume for node_modules to avoid conflicts with Windows host
# and improve performance.
- node_modules_data:/app/node_modules
# Mount PostgreSQL logs for Logstash access (ADR-050)
- postgres_logs:/var/log/postgresql:ro
# Mount Redis logs for Logstash access (ADR-050)
- redis_logs:/var/log/redis:ro
# Mount PM2 logs for Logstash access (ADR-050, ADR-014)
- pm2_logs:/var/log/pm2
ports:
- '80:80' # HTTP redirect to HTTPS (matches production)
- '443:443' # Frontend HTTPS (nginx proxies Vite 5173 → 443)
- '3001:3001' # Backend API
- '8000:8000' # Bugsink error tracking HTTP (ADR-015)
- '8443:8443' # Bugsink error tracking HTTPS (ADR-015)
environment:
# Timezone: PST (America/Los_Angeles) for consistent log timestamps
- TZ=America/Los_Angeles
# Core settings
- NODE_ENV=development
# Database - use service name for Docker networking
- DB_HOST=postgres
- DB_PORT=5432
- DB_USER=postgres
- DB_PASSWORD=postgres
- DB_NAME=flyer_crawler_dev
# Redis - use service name for Docker networking
- REDIS_URL=redis://redis:6379
- REDIS_HOST=redis
- REDIS_PORT=6379
# Frontend URL for CORS
- FRONTEND_URL=http://localhost:3000
# Default JWT secret for development (override in production!)
- JWT_SECRET=dev-jwt-secret-change-in-production
# Worker settings
- WORKER_LOCK_DURATION=120000
# Bugsink error tracking (ADR-015)
- BUGSINK_DB_HOST=postgres
- BUGSINK_DB_PORT=5432
- BUGSINK_DB_NAME=bugsink
- BUGSINK_DB_USER=bugsink
- BUGSINK_DB_PASSWORD=bugsink_dev_password
- BUGSINK_PORT=8000
- BUGSINK_BASE_URL=https://localhost:8443
- BUGSINK_ADMIN_EMAIL=admin@localhost
- BUGSINK_ADMIN_PASSWORD=admin
- BUGSINK_SECRET_KEY=dev-bugsink-secret-key-minimum-50-characters-for-security
# Sentry SDK configuration (points to local Bugsink HTTP)
# Note: Using HTTP with 127.0.0.1 instead of localhost because Sentry SDK
# doesn't accept 'localhost' as a valid hostname in DSN validation
# The browser accesses Bugsink at http://localhost:8000 (nginx proxies to HTTPS for the app)
- SENTRY_DSN=http://cea01396-c562-46ad-b587-8fa5ee6b1d22@127.0.0.1:8000/1
- VITE_SENTRY_DSN=http://d92663cb-73cf-4145-b677-b84029e4b762@127.0.0.1:8000/2
- SENTRY_ENVIRONMENT=development
- VITE_SENTRY_ENVIRONMENT=development
- SENTRY_ENABLED=true
- VITE_SENTRY_ENABLED=true
- SENTRY_DEBUG=true
- VITE_SENTRY_DEBUG=true
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
# Start dev server automatically (works with or without VS Code)
command: /app/scripts/dev-entrypoint.sh
# Healthcheck for the app (once it's running)
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3001/api/health/live']
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# ===================
# PostgreSQL Database
# ===================
postgres:
image: docker.io/postgis/postgis:15-3.4
container_name: flyer-crawler-postgres
ports:
- '5432:5432'
environment:
# Timezone: PST (America/Los_Angeles) for consistent log timestamps
TZ: America/Los_Angeles
# PostgreSQL timezone setting (used by log_timezone and timezone parameters)
PGTZ: America/Los_Angeles
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: flyer_crawler_dev
# Optimize for development
POSTGRES_INITDB_ARGS: '--encoding=UTF8 --locale=C'
volumes:
- postgres_data:/var/lib/postgresql/data
# Mount init scripts to run on first database creation
# Scripts run in alphabetical order: 00-extensions, 01-bugsink
- ./sql/00-init-extensions.sql:/docker-entrypoint-initdb.d/00-init-extensions.sql:ro
- ./sql/01-init-bugsink.sh:/docker-entrypoint-initdb.d/01-init-bugsink.sh:ro
# Mount custom PostgreSQL configuration (ADR-050)
- ./docker/postgres/postgresql.conf.override:/etc/postgresql/postgresql.conf.d/custom.conf:ro
# Create log volume for Logstash access (ADR-050)
- postgres_logs:/var/log/postgresql
# Override postgres command to include custom config (ADR-050)
command: >
postgres
-c config_file=/var/lib/postgresql/data/postgresql.conf
-c hba_file=/var/lib/postgresql/data/pg_hba.conf
-c timezone=America/Los_Angeles
-c log_timezone=America/Los_Angeles
-c log_min_messages=notice
-c client_min_messages=notice
-c logging_collector=on
-c log_destination=stderr
-c log_directory=/var/log/postgresql
-c log_filename=postgresql-%Y-%m-%d.log
-c log_rotation_age=1d
-c log_rotation_size=100MB
-c log_truncate_on_rotation=on
-c log_line_prefix='%t [%p] %u@%d '
-c log_min_duration_statement=1000
-c log_statement=none
-c log_connections=on
-c log_disconnections=on
# Healthcheck ensures postgres is ready before app starts
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres -d flyer_crawler_dev']
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
# ===================
# Redis Cache/Queue
# ===================
redis:
image: docker.io/library/redis:alpine
container_name: flyer-crawler-redis
# Run as root to allow entrypoint to set up log directory permissions
# Redis will drop privileges after setup via gosu in entrypoint
user: root
ports:
- '6379:6379'
environment:
# Timezone: PST (America/Los_Angeles) for consistent log timestamps
TZ: America/Los_Angeles
volumes:
- redis_data:/data
# Create log volume for Logstash access (ADR-050)
- redis_logs:/var/log/redis
# Mount custom entrypoint for log directory setup (ADR-050)
- ./docker/redis/docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh:ro
# Healthcheck ensures redis is ready before app starts
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 5s
timeout: 5s
retries: 10
start_period: 5s
# Enable persistence and file logging for Logstash (ADR-050)
# Redis log levels: debug, verbose, notice (default), warning
# Custom entrypoint sets up log directory with correct permissions
entrypoint: ['/usr/local/bin/docker-entrypoint.sh']
command:
- --appendonly
- 'yes'
- --logfile
- /var/log/redis/redis-server.log
- --loglevel
- notice
# ===================
# Named Volumes
# ===================
volumes:
postgres_data:
name: flyer-crawler-postgres-data
postgres_logs:
name: flyer-crawler-postgres-logs
redis_data:
name: flyer-crawler-redis-data
redis_logs:
name: flyer-crawler-redis-logs
pm2_logs:
name: flyer-crawler-pm2-logs
node_modules_data:
name: flyer-crawler-node-modules
# ===================
# Network Configuration
# ===================
# All services are on the default bridge network.
# Use service names (postgres, redis) as hostnames.