version: '3.9' services: # PostgreSQL - Main relational database postgres: image: postgres:16-alpine container_name: snapdocs-postgres restart: unless-stopped environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password} POSTGRES_DB: snapdocs ports: - "${POSTGRES_PORT:-5432}:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 networks: - snapdocs-network # MongoDB - Document store for page content mongodb: image: mongo:7.0 container_name: snapdocs-mongodb restart: unless-stopped environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USERNAME:-admin} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:-password} MONGO_INITDB_DATABASE: snapdocs ports: - "${MONGODB_PORT:-27017}:27017" volumes: - mongodb_data:/data/db - ./docker/mongodb/init.js:/docker-entrypoint-initdb.d/init.js:ro healthcheck: test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet interval: 10s timeout: 5s retries: 5 networks: - snapdocs-network # Redis - Caching and session management redis: image: redis:7-alpine container_name: snapdocs-redis restart: unless-stopped command: > sh -c ' if [ -n "$${REDIS_PASSWORD}" ]; then redis-server --appendonly yes --requirepass $${REDIS_PASSWORD} else redis-server --appendonly yes fi ' environment: REDIS_PASSWORD: ${REDIS_PASSWORD:-} ports: - "${REDIS_PORT:-6379}:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - snapdocs-network # MinIO - S3-compatible object storage for files minio: image: minio/minio:latest container_name: snapdocs-minio restart: unless-stopped environment: MINIO_ROOT_USER: ${S3_ACCESS_KEY:-minioadmin} MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY:-minioadmin} command: server /data --console-address ":9001" ports: - "${MINIO_API_PORT:-9000}:9000" # API - "${MINIO_CONSOLE_PORT:-9001}:9001" # Console volumes: - minio_data:/data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 10s timeout: 5s retries: 5 networks: - snapdocs-network # Create MinIO bucket on startup minio-setup: image: minio/mc:latest container_name: snapdocs-minio-setup depends_on: minio: condition: service_healthy environment: S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin} S3_BUCKET: ${S3_BUCKET:-snapdocs} entrypoint: > /bin/sh -c " /usr/bin/mc alias set myminio http://minio:9000 $${S3_ACCESS_KEY} $${S3_SECRET_KEY}; /usr/bin/mc mb --ignore-existing myminio/$${S3_BUCKET}; /usr/bin/mc anonymous set public myminio/$${S3_BUCKET}; exit 0; " networks: - snapdocs-network # Next.js Application (production only) app: image: bytescraftio/snapdocs:latest container_name: snapdocs-app restart: unless-stopped profiles: ["production"] ports: - "${APP_PORT:-3000}:3000" environment: NODE_ENV: production DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-password}@postgres:5432/snapdocs MONGODB_URI: mongodb://${MONGO_ROOT_USERNAME:-admin}:${MONGO_ROOT_PASSWORD:-password}@mongodb:27017/snapdocs?authSource=admin REDIS_URL: redis://redis:6379 S3_ENDPOINT: http://minio:9000 S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin} S3_BUCKET: ${S3_BUCKET:-snapdocs} NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:-your-secret-key-here-change-in-production} SOCKET_URL: ${SOCKET_URL:-http://localhost:3000} depends_on: postgres: condition: service_healthy mongodb: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy networks: - snapdocs-network volumes: postgres_data: driver: local mongodb_data: driver: local redis_data: driver: local minio_data: driver: local networks: snapdocs-network: name: snapdocs-network driver: bridge