docker-compose.yml 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. services:
  2. postgres:
  3. image: postgres:16-alpine
  4. container_name: vidreview-db
  5. environment:
  6. POSTGRES_USER: ${POSTGRES_USER:-vidreview}
  7. POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Required}
  8. POSTGRES_DB: ${POSTGRES_DB:-vidreview}
  9. ports:
  10. - '5432:5432'
  11. volumes:
  12. - postgres_data:/var/lib/postgresql/data
  13. healthcheck:
  14. test: ['CMD-SHELL', 'pg_isready -U vidreview']
  15. interval: 5s
  16. timeout: 5s
  17. retries: 5
  18. # ── Init: runs once on fresh deploy ─────────────────────────────────────
  19. # Creates admin account, locks registration, saves credentials to seed_output.
  20. # Skips silently if DB already has an admin (safe to re-run on updates).
  21. init:
  22. build:
  23. context: .
  24. dockerfile: Dockerfile.api
  25. container_name: vidreview-init
  26. entrypoint: ['bash', '/scripts/init-admin.sh']
  27. environment:
  28. DB_HOST: postgres
  29. DB_NAME: ${POSTGRES_DB:-vidreview}
  30. DB_USER: ${POSTGRES_USER:-vidreview}
  31. DB_PASS: ${POSTGRES_PASSWORD:?Required}
  32. API_CONTAINER: vidreview-api
  33. DB_CONTAINER: vidreview-db
  34. OUTPUT_DIR: /seed-output
  35. ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@vidreview.local}
  36. ADMIN_NAME: ${ADMIN_NAME:-Admin}
  37. volumes:
  38. - /var/run/docker.sock:/var/run/docker.sock:rw
  39. - /usr/bin/docker:/usr/bin/docker:rw
  40. - ./scripts:/scripts
  41. - seed_output:/seed-output
  42. depends_on:
  43. postgres:
  44. condition: service_healthy
  45. api:
  46. condition: service_healthy
  47. restart: 'no'
  48. # ── API ─────────────────────────────────────────────────────────────────
  49. api:
  50. build:
  51. context: .
  52. dockerfile: Dockerfile.api
  53. container_name: vidreview-api
  54. environment:
  55. DATABASE_URL: ${DATABASE_URL:?Required}
  56. JWT_SECRET: ${JWT_SECRET:?Required}
  57. JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
  58. API_PORT: 3001
  59. NODE_ENV: ${NODE_ENV:-production}
  60. UPLOAD_DIR: /app/uploads
  61. MAX_FILE_SIZE_MB: ${MAX_FILE_SIZE_MB:-10000}
  62. ALLOWED_ORIGINS: ${ALLOWED_ORIGINS}
  63. FRONTEND_URL: ${FRONTEND_URL}
  64. RESEND_API_KEY: ${RESEND_API_KEY:-}
  65. ports:
  66. - '3001:3001'
  67. depends_on:
  68. postgres:
  69. condition: service_healthy
  70. volumes:
  71. - uploads:/app/uploads
  72. healthcheck:
  73. test: ['CMD-SHELL', 'wget -qO- http://localhost:3001/health || exit 1']
  74. interval: 10s
  75. timeout: 5s
  76. retries: 5
  77. # ── Transcode Worker ─────────────────────────────────────────────────────
  78. worker:
  79. build:
  80. context: .
  81. dockerfile: Dockerfile.api
  82. container_name: vidreview-worker
  83. command: node src/worker/index.js
  84. environment:
  85. DATABASE_URL: ${DATABASE_URL:?Required}
  86. NODE_ENV: ${NODE_ENV:-production}
  87. UPLOAD_DIR: /app/uploads
  88. POLL_INTERVAL_MS: ${POLL_INTERVAL_MS:-2000}
  89. WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-4}
  90. ENCODER: ${ENCODER:-libx264}
  91. depends_on:
  92. postgres:
  93. condition: service_healthy
  94. volumes:
  95. - uploads:/app/uploads
  96. restart: unless-stopped
  97. # ── Caddy Reverse Proxy ──────────────────────────────────────────────────
  98. caddy:
  99. image: caddy:2-alpine
  100. container_name: vidreview-caddy
  101. ports:
  102. - '${CADDY_HTTP_PORT:-8080}:8080'
  103. - '${CADDY_HTTPS_PORT:-8443}:8443'
  104. volumes:
  105. - ./Caddyfile:/etc/caddy/Caddyfile:ro
  106. - caddy_data:/data
  107. - caddy_config:/config
  108. - uploads:/app/uploads
  109. depends_on:
  110. - frontend
  111. - api
  112. # ── Frontend ────────────────────────────────────────────────────────────
  113. frontend:
  114. build:
  115. context: .
  116. dockerfile: Dockerfile.frontend
  117. args:
  118. NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
  119. container_name: vidreview-frontend
  120. environment:
  121. NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
  122. NODE_ENV: ${NODE_ENV:-production}
  123. expose:
  124. - '3000'
  125. depends_on:
  126. api:
  127. condition: service_healthy
  128. volumes:
  129. postgres_data:
  130. uploads:
  131. seed_output:
  132. caddy_data:
  133. caddy_config: