diff --git a/backend/.env b/backend/.env index 24aeccb..daf7b5e 100644 --- a/backend/.env +++ b/backend/.env @@ -2,8 +2,7 @@ NODE_ENV=production POSTGRES_USER=root POSTGRES_PASSWORD=irina76 POSTGRES_DB=imk_db -DATABASE_URL="postgresql://postgres:postgres@localhost:5432/imk_db?schema=public" - +ATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public API_URL="https://imkapi.oblak.solutions" CORS_ORIGIN="[http://localhost:5173,https://www.placebo.mk,https://placebo.mk]" diff --git a/backend/Dockerfile b/backend/Dockerfile index 54b8c6e..beb70fe 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,27 +1,25 @@ +# backend/Dockerfile +FROM node:18-alpine AS builder -FROM node:18.19.1-alpine3.18 +WORKDIR /app -WORKDIR /usr/src/app - -# Install necessary tools and dependencies -RUN apk add --no-cache \ - curl \ - wget \ - python3 \ - make \ - g++ \ - && rm -rf /var/cache/apk/* +# Install necessary tools +RUN apk add --no-cache curl wget postgresql-client # Copy package files COPY package*.json ./ -COPY prisma ./prisma/ -# Install dependencies -# RUN npm ci --only=production +# Install dependencies including dev dependencies for building +RUN npm install + +# Install NestJS CLI globally +RUN npm install -g @nestjs/cli + +# Copy prisma files +COPY prisma ./prisma/ # Generate Prisma client RUN npx prisma generate -RUN npx prisma migrate deploy # Copy source code COPY . . @@ -29,15 +27,39 @@ COPY . . # Build the application RUN npm run build -# Expose port +# Production stage +FROM node:18-alpine + +WORKDIR /app + +# Install necessary tools +RUN apk add --no-cache curl wget postgresql-client + +# Copy package files +COPY package*.json ./ + +# Install production dependencies only +RUN npm install --omit=dev + +# Copy prisma files and generate client +COPY prisma ./prisma/ +RUN npx prisma generate + +# Copy built application from builder stage +COPY --from=builder /app/dist ./dist + +# Create wait-for-db script +RUN echo '#!/bin/sh\n\ + until pg_isready -h postgres -p 5432 -U ${POSTGRES_USER}; do\n\ + echo "Waiting for postgres...";\n\ + sleep 2;\n\ + done\n\ + \n\ + echo "PostgreSQL is ready!"\n\ + \n\ + npx prisma migrate deploy\n\ + node dist/main.js' > /app/start.sh && chmod +x /app/start.sh + EXPOSE 3000 -# Add healthcheck -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD wget -q --spider http://localhost:3000/health || exit 1 - -# Set Node options -ENV NODE_OPTIONS="--max-old-space-size=2048" - -# Start the application directly with node -CMD ["node", "dist/main.js"] +CMD ["/app/start.sh"] diff --git a/backend/package.json b/backend/package.json index 8a43d41..06835c3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -13,6 +13,8 @@ "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main.js", + "db:init": "./scripts/init-db.sh", + "db:test": "./scripts/test-db.sh", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", @@ -21,7 +23,7 @@ "test:e2e": "jest --config ./test/jest-e2e.json", "prisma:generate": "prisma generate", "prisma:migrate:dev": "prisma migrate dev", - "prisma:migrate:deploy": "prisma migrate deploy" + "prisma:migrate": "prisma migrate deploy" }, "dependencies": { "@aws-sdk/client-s3": "^3.679.0", diff --git a/backend/scripts/init-db.sh b/backend/scripts/init-db.sh new file mode 100644 index 0000000..7e0b8a7 --- /dev/null +++ b/backend/scripts/init-db.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# backend/scripts/init-db.sh + +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE $POSTGRES_DB; + GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $POSTGRES_USER; +EOSQL diff --git a/backend/scripts/test-db.sh b/backend/scripts/test-db.sh new file mode 100644 index 0000000..fa6d7cc --- /dev/null +++ b/backend/scripts/test-db.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# backend/scripts/test-db.sh + +echo "Testing database connection..." + +export PGPASSWORD=$POSTGRES_PASSWORD + +echo "Attempting to connect to postgres:5432..." +pg_isready -h postgres -p 5432 -U $POSTGRES_USER + +if [ $? -eq 0 ]; then + echo "Database connection successful!" + psql -h postgres -U $POSTGRES_USER -d $POSTGRES_DB -c "\dt" +else + echo "Database connection failed!" + exit 1 +fi diff --git a/backend/scripts/wait-for-db.sh b/backend/scripts/wait-for-db.sh new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/config/database.config.ts b/backend/src/config/database.config.ts new file mode 100644 index 0000000..9e8b297 --- /dev/null +++ b/backend/src/config/database.config.ts @@ -0,0 +1,5 @@ +export const getDatabaseUrl = () => { + const url = process.env.DATABASE_URL; + console.log("Database URL:", url); // For debugging + return url; +}; diff --git a/backend/src/prisma/prisma.service.ts b/backend/src/prisma/prisma.service.ts index 7ffd32d..ce4dc1b 100644 --- a/backend/src/prisma/prisma.service.ts +++ b/backend/src/prisma/prisma.service.ts @@ -1,13 +1,39 @@ -import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; -import { PrismaClient } from '@prisma/client'; +import { + Injectable, + OnModuleInit, + OnModuleDestroy, + Logger, +} from "@nestjs/common"; +import { PrismaClient } from "@prisma/client"; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { + private readonly logger = new Logger(PrismaService.name); + + constructor() { + super({ + datasources: { + db: { + url: process.env.DATABASE_URL, + }, + }, + }); + this.logger.log( + `Connecting to database with URL: ${process.env.DATABASE_URL}`, + ); + } + async onModuleInit() { - await this.$connect(); + try { + await this.$connect(); + this.logger.log("Successfully connected to database"); + } catch (error) { + this.logger.error("Failed to connect to database:", error); + throw error; + } } async onModuleDestroy() { diff --git a/docker-compose.yml b/docker-compose.yml index 4d3df7f..da36384 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,77 +6,42 @@ services: build: context: ./backend dockerfile: Dockerfile - args: - - NODE_ENV=${NODE_ENV} - - API_URL=${API_URL} - - CORS_ORIGIN=${CORS_ORIGIN} - - DATABASE_URL=${DATABASE_URL} - - JWT_SECRET=${JWT_SECRET} - - SMTP_HOST=${SMTP_HOST} - - SMTP_PORT=${SMTP_PORT} - - SMTP_USER=${SMTP_USER} - - SMTP_PASS=${SMTP_PASS} - - EMAIL_FROM=${EMAIL_FROM} + environment: + - NODE_ENV=production + - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_DB=${POSTGRES_DB} ports: - "3000:3000" - environment: - - NODE_ENV=${NODE_ENV} - - API_URL=${API_URL} - - CORS_ORIGIN=${CORS_ORIGIN} - - DATABASE_URL=${DATABASE_URL} - - SMTP_HOST=${SMTP_HOST} - - SMTP_PORT=${SMTP_PORT} - - SMTP_USER=${SMTP_USER} - - SMTP_PASS=${SMTP_PASS} - - EMAIL_FROM=${EMAIL_FROM} - - CORS_ORIGINS=http://localhost:5173,https://www.placebo.mk,https://placebo.mk - - CORS_CREDENTIALS=true depends_on: postgres: condition: service_healthy - redis: - condition: service_healthy networks: - - app_network + - imk_network postgres: container_name: imk-postgres image: postgres:14-alpine environment: - - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" networks: - - app_network + - imk_network healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 - redis: - container_name: imk-redis - image: redis:alpine - command: redis-server --requirepass ${REDIS_PASSWORD} - environment: - - REDIS_PASSWORD=${REDIS_PASSWORD} - volumes: - - redis_data:/data - networks: - - app_network - healthcheck: - test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] - interval: 10s - timeout: 5s - retries: 3 - networks: - app_network: + imk_network: driver: bridge volumes: postgres_data: - redis_data: