docker-compose.portainer.yml
Rama main · réplica de lectura del repositorio original.
# =============================================================================
# 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