diff --git a/.env.production.example b/.env.production.example index 0d414b9..54eccda 100644 --- a/.env.production.example +++ b/.env.production.example @@ -11,7 +11,7 @@ POSTGRES_PASSWORD=CHANGE_ME_STRONG_PASSWORD # اگر 5432 روی سرور اشغال است مثلاً بگذارید 15432 EXPORT_DB_PORT=15432 -# داخل شبکه compose هاست postgres است (نه localhost) +# داخل شبکه compose هاست postgres است (نه localhost و نه IP عمومی) DATABASE_URL=postgresql://postgres:CHANGE_ME_STRONG_PASSWORD@postgres:5432/lucky_wheel?schema=public REDIS_PASSWORD= diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index 3561d33..24d9383 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -2,15 +2,14 @@ FROM docker.arvancloud.ir/node:20-bookworm # فقط کپی — هیچ install/build داخل ایمیج نیست. # لوکال: pnpm run build:api:release -# مهم: apps/api/release/node_modules باید داخل گیت باشد. WORKDIR /app ENV NODE_ENV=production +ENV PORT=3000 COPY apps/api/release/ ./ EXPOSE 3000 -# به‌جای .bin (روی ویندوز shim می‌سازد) مستقیم entry لینوکسی Prisma -CMD ["sh", "-c", "node node_modules/prisma/build/index.js migrate deploy && node app.js"] +CMD ["sh", "/app/docker-entrypoint.sh"] diff --git a/apps/api/docker-entrypoint.sh b/apps/api/docker-entrypoint.sh new file mode 100644 index 0000000..ae32060 --- /dev/null +++ b/apps/api/docker-entrypoint.sh @@ -0,0 +1,26 @@ +#!/bin/sh +set -eu + +echo "[api] starting entrypoint at $(date -u +%Y-%m-%dT%H:%M:%SZ)" +echo "[api] node=$(node -v) cwd=$(pwd)" +echo "[api] release check: app.js=$(test -f app.js && echo yes || echo NO) prisma=$(test -f node_modules/prisma/build/index.js && echo yes || echo NO)" + +if [ ! -f app.js ]; then + echo "[api] FATAL: app.js missing — release copy failed" >&2 + exit 1 +fi + +if [ ! -f node_modules/prisma/build/index.js ]; then + echo "[api] FATAL: prisma CLI missing — commit apps/api/release/node_modules" >&2 + ls -la node_modules 2>&1 || true + exit 1 +fi + +echo "[api] REDIS_HOST=${REDIS_HOST:-unset} REDIS_PORT=${REDIS_PORT:-unset}" + +echo "[api] running prisma migrate deploy..." +node node_modules/prisma/build/index.js migrate deploy --schema=./prisma/schema.prisma +echo "[api] migrate done" + +echo "[api] launching app.js on 0.0.0.0:${PORT:-3000}" +exec node app.js diff --git a/apps/api/release/app.js b/apps/api/release/app.js index 0312f26..6951637 100644 --- a/apps/api/release/app.js +++ b/apps/api/release/app.js @@ -219153,9 +219153,9 @@ async function bootstrap() { const document2 = swagger_1.SwaggerModule.createDocument(app, swaggerConfig); swagger_1.SwaggerModule.setup("api/docs", app, document2); const port = configService.get("PORT", 3e3); - await app.listen(port); - console.log(`Application is running on: http://localhost:${port}`); - console.log(`Swagger documentation: http://localhost:${port}/api/docs`); + await app.listen(port, "0.0.0.0"); + console.log(`Application is running on: http://0.0.0.0:${port}`); + console.log(`Swagger documentation: http://0.0.0.0:${port}/api/docs`); } __name(bootstrap, "bootstrap"); bootstrap(); diff --git a/apps/api/release/docker-entrypoint.sh b/apps/api/release/docker-entrypoint.sh new file mode 100644 index 0000000..ae32060 --- /dev/null +++ b/apps/api/release/docker-entrypoint.sh @@ -0,0 +1,26 @@ +#!/bin/sh +set -eu + +echo "[api] starting entrypoint at $(date -u +%Y-%m-%dT%H:%M:%SZ)" +echo "[api] node=$(node -v) cwd=$(pwd)" +echo "[api] release check: app.js=$(test -f app.js && echo yes || echo NO) prisma=$(test -f node_modules/prisma/build/index.js && echo yes || echo NO)" + +if [ ! -f app.js ]; then + echo "[api] FATAL: app.js missing — release copy failed" >&2 + exit 1 +fi + +if [ ! -f node_modules/prisma/build/index.js ]; then + echo "[api] FATAL: prisma CLI missing — commit apps/api/release/node_modules" >&2 + ls -la node_modules 2>&1 || true + exit 1 +fi + +echo "[api] REDIS_HOST=${REDIS_HOST:-unset} REDIS_PORT=${REDIS_PORT:-unset}" + +echo "[api] running prisma migrate deploy..." +node node_modules/prisma/build/index.js migrate deploy --schema=./prisma/schema.prisma +echo "[api] migrate done" + +echo "[api] launching app.js on 0.0.0.0:${PORT:-3000}" +exec node app.js diff --git a/apps/api/scripts/bundle-release.cjs b/apps/api/scripts/bundle-release.cjs index e64ef84..de4e71f 100644 --- a/apps/api/scripts/bundle-release.cjs +++ b/apps/api/scripts/bundle-release.cjs @@ -34,6 +34,9 @@ async function main() { } cpSync(path.join(root, 'prisma'), prismaDest, { recursive: true }); + // entrypoint برای لاگ واضح استارت در Dokploy + cpSync(path.join(root, 'docker-entrypoint.sh'), path.join(releaseDir, 'docker-entrypoint.sh')); + const releasePkg = { name: 'lucky-wheel-api-release', private: true, diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index 2825753..2f1ab46 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -77,9 +77,10 @@ async function bootstrap() { SwaggerModule.setup('api/docs', app, document); const port = configService.get('PORT', 3000); - await app.listen(port); - console.log(`Application is running on: http://localhost:${port}`); - console.log(`Swagger documentation: http://localhost:${port}/api/docs`); + // Dokploy/Traefik از شبکه Docker وصل می‌شود — باید روی همه اینترفیس‌ها listen کند + await app.listen(port, '0.0.0.0'); + console.log(`Application is running on: http://0.0.0.0:${port}`); + console.log(`Swagger documentation: http://0.0.0.0:${port}/api/docs`); } bootstrap();