This commit is contained in:
dimitar 2025-03-31 17:23:52 +02:00
parent d2a5f8095d
commit cd2ace68e6
9 changed files with 123 additions and 78 deletions

View File

@ -2,8 +2,7 @@ NODE_ENV=production
POSTGRES_USER=root POSTGRES_USER=root
POSTGRES_PASSWORD=irina76 POSTGRES_PASSWORD=irina76
POSTGRES_DB=imk_db 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" API_URL="https://imkapi.oblak.solutions"
CORS_ORIGIN="[http://localhost:5173,https://www.placebo.mk,https://placebo.mk]" CORS_ORIGIN="[http://localhost:5173,https://www.placebo.mk,https://placebo.mk]"

View File

@ -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
RUN apk add --no-cache curl wget postgresql-client
# Install necessary tools and dependencies
RUN apk add --no-cache \
curl \
wget \
python3 \
make \
g++ \
&& rm -rf /var/cache/apk/*
# Copy package files # Copy package files
COPY package*.json ./ COPY package*.json ./
COPY prisma ./prisma/
# Install dependencies # Install dependencies including dev dependencies for building
# RUN npm ci --only=production RUN npm install
# Install NestJS CLI globally
RUN npm install -g @nestjs/cli
# Copy prisma files
COPY prisma ./prisma/
# Generate Prisma client # Generate Prisma client
RUN npx prisma generate RUN npx prisma generate
RUN npx prisma migrate deploy
# Copy source code # Copy source code
COPY . . COPY . .
@ -29,15 +27,39 @@ COPY . .
# Build the application # Build the application
RUN npm run build 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 EXPOSE 3000
# Add healthcheck CMD ["/app/start.sh"]
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"]

View File

@ -13,6 +13,8 @@
"start:dev": "nest start --watch", "start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch", "start:debug": "nest start --debug --watch",
"start:prod": "node dist/main.js", "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", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest", "test": "jest",
"test:watch": "jest --watch", "test:watch": "jest --watch",
@ -21,7 +23,7 @@
"test:e2e": "jest --config ./test/jest-e2e.json", "test:e2e": "jest --config ./test/jest-e2e.json",
"prisma:generate": "prisma generate", "prisma:generate": "prisma generate",
"prisma:migrate:dev": "prisma migrate dev", "prisma:migrate:dev": "prisma migrate dev",
"prisma:migrate:deploy": "prisma migrate deploy" "prisma:migrate": "prisma migrate deploy"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.679.0", "@aws-sdk/client-s3": "^3.679.0",

View File

@ -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

View File

@ -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

View File

View File

@ -0,0 +1,5 @@
export const getDatabaseUrl = () => {
const url = process.env.DATABASE_URL;
console.log("Database URL:", url); // For debugging
return url;
};

View File

@ -1,13 +1,39 @@
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import {
import { PrismaClient } from '@prisma/client'; Injectable,
OnModuleInit,
OnModuleDestroy,
Logger,
} from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
@Injectable() @Injectable()
export class PrismaService export class PrismaService
extends PrismaClient extends PrismaClient
implements OnModuleInit, OnModuleDestroy 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() { 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() { async onModuleDestroy() {

View File

@ -6,77 +6,42 @@ services:
build: build:
context: ./backend context: ./backend
dockerfile: Dockerfile dockerfile: Dockerfile
args: environment:
- NODE_ENV=${NODE_ENV} - NODE_ENV=production
- API_URL=${API_URL} - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
- CORS_ORIGIN=${CORS_ORIGIN} - POSTGRES_USER=${POSTGRES_USER}
- DATABASE_URL=${DATABASE_URL} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- JWT_SECRET=${JWT_SECRET} - POSTGRES_DB=${POSTGRES_DB}
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT}
- SMTP_USER=${SMTP_USER}
- SMTP_PASS=${SMTP_PASS}
- EMAIL_FROM=${EMAIL_FROM}
ports: ports:
- "3000:3000" - "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: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
redis:
condition: service_healthy
networks: networks:
- app_network - imk_network
postgres: postgres:
container_name: imk-postgres container_name: imk-postgres
image: postgres:14-alpine image: postgres:14-alpine
environment: environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER} - POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB} - POSTGRES_DB=${POSTGRES_DB}
volumes: volumes:
- postgres_data:/var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks: networks:
- app_network - imk_network
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 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: networks:
app_network: imk_network:
driver: bridge driver: bridge
volumes: volumes:
postgres_data: postgres_data:
redis_data: