Ctrl K
ComunidadGuías…

docker-compose.portainer.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# =============================================================================
# SocialiseIT Production Docker Compose
# Designed for Portainer deployment with git-based pulls
# =============================================================================
#
# USAGE:
#   1. Create stack.env from stack.env.example with your values
#   2. Deploy via Portainer: Stacks -> Add Stack -> Repository
#   3. Set compose file: docker-compose.portainer.yml
#   4. Add environment variables from stack.env
#   5. Disable Re-pull image; app images are built from the repository locally
#
# REQUIREMENTS:
#   - Docker Standalone with Compose support for pull_policy: build (not Swarm)
#   - External network 'proxy-net' must exist: docker network create proxy-net
#   - Nginx Proxy Manager configured to forward traffic
# =============================================================================

services:
  # ---------------------------------------------------------------------------
  # Init Container -- generates secrets on first boot, then exits
  # ---------------------------------------------------------------------------
  init:
    image: alpine:3.19
    container_name: socialiseit-init
    command: sh /docker-init.sh
    volumes:
      - ./docker-init.sh:/docker-init.sh:ro
      - secrets_data:/secrets
    restart: "no"

  # ---------------------------------------------------------------------------
  # Next.js Web Application (Production)
  # ---------------------------------------------------------------------------
  webapp:
    build:
      context: .
      dockerfile: Dockerfile
      target: webapp
    # Rebuild from the checked-out source on each deployment (cached layers reused).
    pull_policy: build
    container_name: socialiseit-webapp
    restart: unless-stopped
    networks:
      - default
      - proxy-net
    # NO external ports - traffic routed through Nginx Proxy Manager
    environment:
      # Database
      - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@socialiseit-postgres:5432/${POSTGRES_DB:-socialiseit}
      - POSTGRES_PRISMA_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@socialiseit-postgres:5432/${POSTGRES_DB:-socialiseit}
      - POSTGRES_URL_NON_POOLING=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@socialiseit-postgres:5432/${POSTGRES_DB:-socialiseit}
      # Redis (with password authentication)
      - REDIS_URL=redis://:${REDIS_PASSWORD:-socialiseit_redis}@socialiseit-redis:6379
      # Application
      - NODE_ENV=production
      - NEXTAUTH_URL=${APP_URL}
      - NEXTAUTH_SECRET=${AUTH_SECRET}
      - AUTH_SECRET=${AUTH_SECRET}
      # Encryption (CRITICAL: Keep consistent across deployments!)
      - ENCRYPTION_KEY=${ENCRYPTION_KEY}
      # MinIO/S3 Storage
      - S3_ENDPOINT=${S3_ENDPOINT:-http://socialiseit-minio:9000}
      - S3_PUBLIC_URL=${S3_PUBLIC_URL:-}
      - S3_ACCESS_KEY=${MINIO_ROOT_USER:-minioadmin}
      - S3_SECRET_KEY=${MINIO_ROOT_PASSWORD:-minioadmin}
      - S3_BUCKET=${S3_BUCKET:-socialiseit}
      # OAuth Providers
      - AUTH_GOOGLE_ID=${AUTH_GOOGLE_ID:-}
      - AUTH_GOOGLE_SECRET=${AUTH_GOOGLE_SECRET:-}
      # Social Platform APIs
      - INSTAGRAM_CLIENT_ID=${INSTAGRAM_CLIENT_ID:-}
      - INSTAGRAM_CLIENT_SECRET=${INSTAGRAM_CLIENT_SECRET:-}
      - FACEBOOK_APP_ID=${FACEBOOK_APP_ID:-}
      - FACEBOOK_APP_SECRET=${FACEBOOK_APP_SECRET:-}
      - TIKTOK_CLIENT_KEY=${TIKTOK_CLIENT_KEY:-}
      - TIKTOK_CLIENT_SECRET=${TIKTOK_CLIENT_SECRET:-}
      - YOUTUBE_API_KEY=${YOUTUBE_API_KEY:-}
      - YOUTUBE_CLIENT_ID=${YOUTUBE_CLIENT_ID:-}
      - YOUTUBE_CLIENT_SECRET=${YOUTUBE_CLIENT_SECRET:-}
      # AI Services
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
    depends_on:
      init:
        condition: service_completed_successfully
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    volumes:
      # Persist uploaded media files across container rebuilds
      - uploads_data:/app/public/uploads
      - secrets_data:/secrets:ro
    healthcheck:
      test: [ "CMD", "curl", "-f", "http://localhost:3000/api/health" ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '1.0'

  # ---------------------------------------------------------------------------
  # Background Job Worker
  # ---------------------------------------------------------------------------
  worker:
    build:
      context: .
      dockerfile: Dockerfile
      target: worker
    pull_policy: build
    container_name: socialiseit-worker
    restart: unless-stopped
    networks:
      - default
    environment:
      - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@socialiseit-postgres:5432/${POSTGRES_DB:-socialiseit}
      - REDIS_URL=redis://:${REDIS_PASSWORD:-socialiseit_redis}@socialiseit-redis:6379
      - ENCRYPTION_KEY=${ENCRYPTION_KEY}
      - NODE_ENV=production
      - NEXTAUTH_URL=${APP_URL}
      # Required for file_url video uploads (Facebook downloads from this URL)
      - APP_URL=${APP_URL}
    depends_on:
      init:
        condition: service_completed_successfully
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      webapp:
        condition: service_healthy
    volumes:
      # CRITICAL: Share uploads with webapp so worker can read files for publishing
      - uploads_data:/app/public/uploads
      - secrets_data:/secrets:ro
    # Why: Video uploads load 90MB+ files into memory, 512MB is too small
    stop_grace_period: 120s

  # ---------------------------------------------------------------------------
  # PostgreSQL Database
  # ---------------------------------------------------------------------------
  postgres:
    image: postgres:16.2-alpine
    container_name: socialiseit-postgres
    restart: unless-stopped
    networks:
      - default
    # NO external ports - internal only
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
      POSTGRES_DB: ${POSTGRES_DB:-socialiseit}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}" ]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '1.0'

  # ---------------------------------------------------------------------------
  # Redis for Caching and Job Queues
  # ---------------------------------------------------------------------------
  redis:
    image: redis:7.2-alpine
    container_name: socialiseit-redis
    restart: unless-stopped
    networks:
      - default
    # NO external ports - internal only
    # Password authentication for production security
    command: redis-server --requirepass ${REDIS_PASSWORD:-socialiseit_redis}
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-socialiseit_redis}
    volumes:
      - redis_data:/data
    healthcheck:
      test: [ "CMD-SHELL", "redis-cli -a $$REDIS_PASSWORD ping | grep -q PONG" ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 5s
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'

  # ---------------------------------------------------------------------------
  # MinIO S3-Compatible Object Storage
  # ---------------------------------------------------------------------------
  minio:
    image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
    container_name: socialiseit-minio
    restart: unless-stopped
    networks:
      - default
      - proxy-net # Optional: if you want CDN access via NPM
    command: server /data --console-address ":9001"
    # NO external ports - access via NPM or internal only
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
    volumes:
      - minio_data:/data
    healthcheck:
      test: [ "CMD", "curl", "-f", "http://localhost:9000/minio/health/live" ]
      interval: 30s
      timeout: 20s
      retries: 3

# =============================================================================
# Networks
# =============================================================================
networks:
  default:
    name: socialiseit-internal
  proxy-net:
    external: true
    # REQUIRED: Run once on server: docker network create proxy-net

# =============================================================================
# Volumes (Persistent Data)
# =============================================================================
volumes:
  secrets_data:
    name: socialiseit-secrets
  postgres_data:
    name: socialiseit-postgres-data
  redis_data:
    name: socialiseit-redis-data
  minio_data:
    name: socialiseit-minio-data
  uploads_data:
    name: socialiseit-uploads-data