docker-compose.yml 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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:-500}
  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. depends_on:
  90. postgres:
  91. condition: service_healthy
  92. volumes:
  93. - uploads:/app/uploads
  94. restart: unless-stopped
  95. # ── Caddy Reverse Proxy ──────────────────────────────────────────────────
  96. caddy:
  97. image: caddy:2-alpine
  98. container_name: vidreview-caddy
  99. ports:
  100. - '${CADDY_HTTP_PORT:-8080}:8080'
  101. - '${CADDY_HTTPS_PORT:-8443}:8443'
  102. volumes:
  103. - ./Caddyfile:/etc/caddy/Caddyfile:ro
  104. - caddy_data:/data
  105. - caddy_config:/config
  106. depends_on:
  107. - frontend
  108. - api
  109. # ── Frontend ────────────────────────────────────────────────────────────
  110. frontend:
  111. build:
  112. context: .
  113. dockerfile: Dockerfile.frontend
  114. container_name: vidreview-frontend
  115. environment:
  116. NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
  117. NODE_ENV: ${NODE_ENV:-production}
  118. expose:
  119. - '3000'
  120. depends_on:
  121. api:
  122. condition: service_healthy
  123. volumes:
  124. postgres_data:
  125. uploads:
  126. seed_output:
  127. caddy_data:
  128. caddy_config: