Ctrl K
ComunidadGuías…

docker-compose.dev.yml

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

Archivo original ↗Preguntar a KiBot
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: freeframe
      POSTGRES_PASSWORD: freeframe
      POSTGRES_DB: freeframe
    ports:
      - "5433:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U freeframe"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5

  # S3 storage. Silo is a maintained fork of MinIO: the minio/minio and minio/mc
  # images can no longer be pulled from Docker Hub (#461). It reads the same
  # MINIO_* variables and opens an existing miniodata volume as is, so the
  # service keeps its name and S3_ENDPOINT stays http://minio:9000.
  # Browser CORS is not set here: the API writes the bucket's CORS rules at
  # startup from FRONTEND_URL and CORS_ALLOW_ORIGINS.
  minio:
    image: pgsty/silo:RELEASE.2026-09-16T00-00-00Z
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - miniodata:/data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 5s
      timeout: 5s
      retries: 5

  minio-init:
    image: pgsty/mc:RELEASE.2026-09-16T00-00-00Z
    depends_on:
      minio:
        condition: service_healthy
    entrypoint: >
      /bin/sh -c "
      mc alias set local http://minio:9000 minioadmin minioadmin;
      mc mb --ignore-existing local/freeframe;
      mc anonymous set download local/freeframe;
      exit 0;
      "

  api:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    ports:
      - "8000:8000"
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://freeframe:freeframe@postgres:5432/freeframe
      REDIS_URL: redis://redis:6379/0
      # Storage: "minio" for local MinIO (dev), "s3" for AWS S3 (prod)
      S3_STORAGE: ${S3_STORAGE:-minio}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
      S3_ENDPOINT: http://minio:9000
      S3_BUCKET: ${S3_BUCKET:-freeframe}
      S3_REGION: ${S3_REGION:-us-east-1}
      S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT:-http://localhost:9000}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      minio:
        condition: service_healthy
    volumes:
      - ./apps/api:/workspace/apps/api
      - ./packages/transcoder:/workspace/packages/transcoder
    command: >
      sh -c "cd /workspace/apps/api && alembic upgrade head && cd /workspace && uvicorn apps.api.main:app --host 0.0.0.0 --port 8000 --reload"

  worker:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://freeframe:freeframe@postgres:5432/freeframe
      REDIS_URL: redis://redis:6379/0
      S3_STORAGE: ${S3_STORAGE:-minio}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
      S3_ENDPOINT: http://minio:9000
      S3_BUCKET: ${S3_BUCKET:-freeframe}
      S3_REGION: ${S3_REGION:-us-east-1}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      minio:
        condition: service_healthy
    volumes:
      - ./apps/api:/workspace/apps/api
      - ./packages/transcoder:/workspace/packages/transcoder
    command: celery -A apps.api.tasks.celery_app worker -Q transcoding -c ${TRANSCODING_CONCURRENCY:-2} --loglevel=info

  email_worker:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://freeframe:freeframe@postgres:5432/freeframe
      REDIS_URL: redis://redis:6379/0
      S3_STORAGE: ${S3_STORAGE:-minio}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
      S3_ENDPOINT: http://minio:9000
      S3_BUCKET: ${S3_BUCKET:-freeframe}
      S3_REGION: ${S3_REGION:-us-east-1}
    depends_on:
      redis:
        condition: service_healthy
    volumes:
      - ./apps/api:/workspace/apps/api
      - ./packages/transcoder:/workspace/packages/transcoder
    command: celery -A apps.api.tasks.celery_app worker -Q email_high,email_low -c ${EMAIL_CONCURRENCY:-2} --loglevel=info

  # Housekeeping worker. Present in dev as well as prod so the periodic tasks
  # are exercised locally: #240 was invisible for months precisely because dev
  # ran neither this worker nor beat.
  #
  # NOTE: this means your local stack really does delete things on a schedule.
  # Within the hour, reap_stale_uploads soft-deletes AssetVersions stuck in
  # uploading/failed past STALE_UPLOAD_TIMEOUT_HOURS and drops their S3 objects
  # (a failed version whose original is still in storage is kept);
  # at 03:00 UTC, cleanup_soft_deleted hard-deletes anything soft-deleted past
  # SOFT_DELETE_RETENTION_DAYS, cascade and S3 reclaim included. Both take `0`
  # in your .env to switch them off if you keep long-lived local data.
  maintenance_worker:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://freeframe:freeframe@postgres:5432/freeframe
      REDIS_URL: redis://redis:6379/0
      S3_STORAGE: ${S3_STORAGE:-minio}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
      S3_ENDPOINT: http://minio:9000
      S3_BUCKET: ${S3_BUCKET:-freeframe}
      S3_REGION: ${S3_REGION:-us-east-1}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      minio:
        condition: service_healthy
    volumes:
      - ./apps/api:/workspace/apps/api
      - ./packages/transcoder:/workspace/packages/transcoder
    command: celery -A apps.api.tasks.celery_app worker -Q maintenance -c ${MAINTENANCE_CONCURRENCY:-1} --loglevel=info

  beat:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://freeframe:freeframe@postgres:5432/freeframe
      REDIS_URL: redis://redis:6379/0
      S3_STORAGE: ${S3_STORAGE:-minio}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-minioadmin}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-minioadmin}
      S3_ENDPOINT: http://minio:9000
      S3_BUCKET: ${S3_BUCKET:-freeframe}
      S3_REGION: ${S3_REGION:-us-east-1}
    depends_on:
      redis:
        condition: service_healthy
    volumes:
      - ./apps/api:/workspace/apps/api
      - ./packages/transcoder:/workspace/packages/transcoder
    command: celery -A apps.api.tasks.celery_app beat --loglevel=info -s /tmp/celerybeat-schedule

  web:
    image: node:20-alpine
    working_dir: /app
    ports:
      - "3000:3000"
    environment:
      - NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://localhost:8000}
      # Sub-path deployments: empty serves the app from the domain root.
      - NEXT_PUBLIC_BASE_PATH=${NEXT_PUBLIC_BASE_PATH:-}
      # Server-to-server, for the branding Next renders into the first byte.
      # NEXT_PUBLIC_API_URL is written for the browser, and inside this
      # container `localhost:8000` is this container, not the API.
      - API_INTERNAL_URL=${API_INTERNAL_URL:-http://api:8000}
      - NODE_ENV=development
      - HOSTNAME=0.0.0.0
    volumes:
      - ./apps/web:/app
      - web_node_modules:/app/node_modules
    command: sh -c "npm install && npx next dev --hostname 0.0.0.0"
    depends_on:
      - api
    healthcheck:
      # See docker-compose.prod.yml: `/` is a 404 when a base path is set.
      test:
        [
          "CMD-SHELL",
          "wget -q --spider \"http://localhost:3000${NEXT_PUBLIC_BASE_PATH:-}/login\"",
        ]
      interval: 30s
      timeout: 10s
      retries: 10
      start_period: 60s

volumes:
  pgdata:
  miniodata:
  redisdata:
  web_node_modules: