Fix master-api Docker runtime: flat deps, explicit env, longer health start period.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jos Vooges | STH 2026-08-25 00:48:41 +02:00
parent 96a0bbface
commit 4e232e8ef6
3 changed files with 62 additions and 41 deletions

View file

@ -25,13 +25,13 @@
"fastify": "^5.2.1",
"ioredis": "^5.4.2",
"nanoid": "^5.0.9",
"prisma": "^6.3.1",
"stremio-addon-sdk": "^1.6.10",
"zod": "^3.24.1"
},
"devDependencies": {
"@types/node": "^22.10.7",
"@types/ws": "^8.5.14",
"prisma": "^6.3.1",
"tsx": "^4.19.2",
"typescript": "^5.7.3"
}

View file

@ -2,33 +2,49 @@ FROM node:20-alpine AS base
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
WORKDIR /app
FROM base AS deps
COPY package.json pnpm-workspace.yaml ./
COPY apps/master-api/package.json ./apps/master-api/
COPY packages/shared-types/package.json ./packages/shared-types/
COPY packages/protocol/package.json ./packages/protocol/
RUN pnpm install --no-frozen-lockfile
FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/apps ./apps
COPY --from=deps /app/packages ./packages
COPY package.json pnpm-workspace.yaml ./
COPY packages ./packages
COPY apps/master-api ./apps/master-api
RUN pnpm --filter @media-cluster/shared-types build \
&& pnpm --filter @media-cluster/protocol build
COPY packages ./packages
RUN pnpm install --no-frozen-lockfile
RUN pnpm --filter @media-cluster/shared-types build
RUN pnpm --filter @media-cluster/protocol build
WORKDIR /app/apps/master-api
RUN pnpm exec prisma generate && pnpm build
RUN pnpm exec prisma generate
RUN pnpm build
# Assemble a flat runtime directory (avoids broken pnpm symlinks in final image)
WORKDIR /app
RUN mkdir -p /out/node_modules/@media-cluster \
&& cp -R apps/master-api/dist /out/dist \
&& cp -R apps/master-api/prisma /out/prisma \
&& cp apps/master-api/package.json /out/package.json \
&& cp -R packages/shared-types /out/node_modules/@media-cluster/shared-types \
&& cp -R packages/protocol /out/node_modules/@media-cluster/protocol
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN apk add --no-cache openssl wget
COPY --from=builder /app/apps/master-api/dist ./dist
COPY --from=builder /app/apps/master-api/package.json ./package.json
COPY --from=builder /app/apps/master-api/prisma ./prisma
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/packages ./packages
RUN apk add --no-cache openssl wget python3 make g++
COPY --from=builder /out/ ./
# Drop workspace: protocol deps; keep prisma CLI for migrate
RUN node -e "\
const fs=require('fs');\
const p=JSON.parse(fs.readFileSync('package.json','utf8'));\
delete p.dependencies['@media-cluster/protocol'];\
delete p.dependencies['@media-cluster/shared-types'];\
p.dependencies.prisma = (p.devDependencies && p.devDependencies.prisma) || '6.3.1';\
delete p.devDependencies;\
delete p.scripts;\
fs.writeFileSync('package.json', JSON.stringify(p, null, 2));"
RUN npm install --omit=dev \
&& npx prisma generate \
&& apk del python3 make g++
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=5 \
CMD wget -qO- http://127.0.0.1:3000/health || exit 1
CMD ["sh", "-c", "npx prisma migrate deploy && node dist/app.js"]

View file

@ -1,9 +1,8 @@
# Docker Compose tuned for Dokploy
# Deploy as: Compose application → Git provider → compose path:
# deploy/docker/docker-compose.dokploy.yml
# Docker Compose for Dokploy
# Compose path: deploy/docker/docker-compose.dokploy.yml
#
# Set environment variables in the Dokploy UI (Environment tab).
# Dokploy writes them to .env next to this compose file.
# Put secrets in Dokploy Environment tab (NOT env_file).
# Dokploy injects them for ${VAR} substitution.
services:
postgres:
@ -11,15 +10,16 @@ services:
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-media}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
POSTGRES_DB: ${POSTGRES_DB:-media_cluster}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER:-media} -d $${POSTGRES_DB:-media_cluster}"]
test: ["CMD-SHELL", "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""]
interval: 10s
timeout: 5s
retries: 5
retries: 10
start_period: 10s
networks:
- media-cluster
@ -32,7 +32,7 @@ services:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
retries: 10
networks:
- media-cluster
@ -41,28 +41,35 @@ services:
context: ../..
dockerfile: deploy/docker/Dockerfile.master-api
restart: unless-stopped
env_file:
- .env
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3000
PORT: "3000"
DATABASE_URL: postgresql://${POSTGRES_USER:-media}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-media_cluster}
REDIS_URL: redis://redis:6379
SESSION_SECRET: ${SESSION_SECRET:?SESSION_SECRET is required}
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@localhost}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-changeme123}
PUBLIC_URL: ${PUBLIC_URL:-https://master.vonas.nl}
TMDB_API_KEY: ${TMDB_API_KEY:-}
PLAYBACK_IDLE_TIMEOUT_SECONDS: ${PLAYBACK_IDLE_TIMEOUT_SECONDS:-1200}
PLAYBACK_ABSOLUTE_LIFETIME_SECONDS: ${PLAYBACK_ABSOLUTE_LIFETIME_SECONDS:-43200}
NODE_HEARTBEAT_INTERVAL_SECONDS: ${NODE_HEARTBEAT_INTERVAL_SECONDS:-30}
NODE_OFFLINE_THRESHOLD_SECONDS: ${NODE_OFFLINE_THRESHOLD_SECONDS:-90}
HIDE_UNAVAILABLE_TITLES: ${HIDE_UNAVAILABLE_TITLES:-false}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
# Host ports (avoid Dokploy UI on :3000)
ports:
- "3100:3000"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 40s
retries: 10
start_period: 90s
networks:
media-cluster:
aliases:
@ -78,12 +85,10 @@ services:
environment:
HOSTNAME: 0.0.0.0
PORT: "3000"
# Prefer compose DNS; fallback via published host port
MASTER_API_URL: http://master-api:3000
NEXT_PUBLIC_API_URL: http://master-api:3000
depends_on:
master-api:
condition: service_healthy
- master-api
ports:
- "3101:3000"
networks: