From 78a68b3567fed5624b14bf1e8cead789e2a866c8 Mon Sep 17 00:00:00 2001 From: "s.esmaeili" Date: Wed, 9 Sep 2026 19:39:13 +0330 Subject: [PATCH] chore: add docker configuration --- .env.example | 10 +++++++ apps/admin-panel/Dockerfile | 37 +++++++++++++++++++++++++ apps/api/Dockerfile | 45 +++++++++++++++++++++++++++++++ apps/user-app/Dockerfile | 37 +++++++++++++++++++++++++ docker-compose.yml | 54 +++++++++++++++++++++++++++++++++++++ nginx-spa.conf | 18 +++++++++++++ 6 files changed, 201 insertions(+) create mode 100644 .env.example create mode 100644 apps/admin-panel/Dockerfile create mode 100644 apps/api/Dockerfile create mode 100644 apps/user-app/Dockerfile create mode 100644 docker-compose.yml create mode 100644 nginx-spa.conf diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..dc3f533 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# Database configuration +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres +POSTGRES_DB=goldbank + +# Prisma connection string +DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public + +# API Configuration +PORT=3000 diff --git a/apps/admin-panel/Dockerfile b/apps/admin-panel/Dockerfile new file mode 100644 index 0000000..68430da --- /dev/null +++ b/apps/admin-panel/Dockerfile @@ -0,0 +1,37 @@ +FROM node:20-alpine AS alpine +RUN apk update +RUN apk add --no-cache libc6-compat + +# Setup pnpm +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable pnpm + +FROM alpine AS builder +WORKDIR /app +RUN pnpm i -g turbo +COPY . . +RUN turbo prune admin-panel --docker + +FROM alpine AS installer +WORKDIR /app +# First install dependencies +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +RUN pnpm install + +# Build the project +COPY --from=builder /app/out/full/ . +COPY turbo.json turbo.json +RUN pnpm turbo run build --filter=admin-panel... + +FROM nginx:alpine AS runner +# Copy custom Nginx configuration +COPY nginx-spa.conf /etc/nginx/conf.d/default.conf + +# Copy the built files from the installer stage +COPY --from=installer /app/apps/admin-panel/dist /usr/share/nginx/html + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile new file mode 100644 index 0000000..266b57b --- /dev/null +++ b/apps/api/Dockerfile @@ -0,0 +1,45 @@ +FROM node:20-alpine AS alpine +RUN apk update +RUN apk add --no-cache libc6-compat openssl + +# Setup pnpm +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable pnpm + +FROM alpine AS builder +WORKDIR /app +RUN pnpm i -g turbo +COPY . . +RUN turbo prune api --docker + +FROM alpine AS installer +WORKDIR /app + +# First install dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +RUN pnpm install + +# Build the project and its dependencies +COPY --from=builder /app/out/full/ . +COPY turbo.json turbo.json +# Generate prisma client before building +RUN pnpm --filter api exec prisma generate +RUN pnpm turbo run build --filter=api... + +FROM alpine AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nestjs +USER nestjs + +COPY --from=installer /app . + +WORKDIR /app/apps/api + +EXPOSE 3000 +CMD ["node", "dist/main.js"] diff --git a/apps/user-app/Dockerfile b/apps/user-app/Dockerfile new file mode 100644 index 0000000..128351d --- /dev/null +++ b/apps/user-app/Dockerfile @@ -0,0 +1,37 @@ +FROM node:20-alpine AS alpine +RUN apk update +RUN apk add --no-cache libc6-compat + +# Setup pnpm +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable pnpm + +FROM alpine AS builder +WORKDIR /app +RUN pnpm i -g turbo +COPY . . +RUN turbo prune user-app --docker + +FROM alpine AS installer +WORKDIR /app +# First install dependencies +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +RUN pnpm install + +# Build the project +COPY --from=builder /app/out/full/ . +COPY turbo.json turbo.json +RUN pnpm turbo run build --filter=user-app... + +FROM nginx:alpine AS runner +# Copy custom Nginx configuration +COPY nginx-spa.conf /etc/nginx/conf.d/default.conf + +# Copy the built files from the installer stage +COPY --from=installer /app/apps/user-app/dist /usr/share/nginx/html + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cde84e5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + db: + image: postgres:15-alpine + container_name: goldbank_db + environment: + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} + POSTGRES_DB: ${POSTGRES_DB:-goldbank} + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + restart: unless-stopped + + api: + build: + context: . + dockerfile: apps/api/Dockerfile + container_name: goldbank_api + depends_on: + - db + environment: + - DATABASE_URL=${DATABASE_URL:-postgresql://postgres:postgres@db:5432/goldbank?schema=public} + - PORT=${PORT:-3000} + ports: + - "3000:3000" + restart: unless-stopped + + admin-panel: + build: + context: . + dockerfile: apps/admin-panel/Dockerfile + container_name: goldbank_admin_panel + ports: + - "8080:80" + restart: unless-stopped + depends_on: + - api + + user-app: + build: + context: . + dockerfile: apps/user-app/Dockerfile + container_name: goldbank_user_app + ports: + - "8081:80" + restart: unless-stopped + depends_on: + - api + +volumes: + postgres_data: diff --git a/nginx-spa.conf b/nginx-spa.conf new file mode 100644 index 0000000..6ad7ac2 --- /dev/null +++ b/nginx-spa.conf @@ -0,0 +1,18 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + # Optional: Cache static assets + location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg)$ { + expires 6M; + access_log off; + add_header Cache-Control "public"; + } +}