diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..bb15e05 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,45 @@ +# Dependencies +node_modules +.pnpm-store + +# Build output +.next +out + +# Environment files +.env +.env.local +.env.*.local + +# Git +.git +.gitignore + +# Docker +Dockerfile* +docker-compose* +.dockerignore + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# OS files +.DS_Store +Thumbs.db + +# Editor +.vscode +.idea +*.swp +*.swo + +# Testing +coverage +.nyc_output + +# Misc +README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7bbe416 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# ─── Stage 1: deps ─────────────────────────────────────────────────────────── +FROM node:22-alpine AS deps +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /app + +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +RUN pnpm install --frozen-lockfile + +# ─── Stage 2: builder ──────────────────────────────────────────────────────── +FROM node:22-alpine AS builder +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Build-time env (optional — override at runtime via docker-compose) +ARG API_URL +ENV API_URL=${API_URL} + +RUN pnpm build + +# ─── Stage 3: runner (production) ──────────────────────────────────────────── +FROM node:22-alpine AS runner + +WORKDIR /app + +ENV NODE_ENV=production +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 + +# Security: run as non-root user +RUN addgroup --system --gid 1001 nodejs \ + && adduser --system --uid 1001 nextjs + +# Copy only what's needed to run +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..9d14086 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,12 @@ +FROM node:22-alpine + +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /app + +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +RUN pnpm install + +EXPOSE 3000 + +CMD ["pnpm", "dev"] diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..4d3e7af --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,18 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile.dev + image: getgreen-uz:dev + container_name: getgreen-uz-dev + restart: unless-stopped + ports: + - "${PORT:-3000}:3000" + environment: + NODE_ENV: development + API_URL: ${API_URL:-https://api.quyoshli.uz/api} + WATCHPACK_POLLING: "true" # fayl o'zgarishlarini Docker ichida aniqlash uchun + volumes: + - .:/app + - /app/node_modules # host node_modules ni override qilmaslik uchun + - /app/.next # build cache ni preserve qilish uchun diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..932c615 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile + target: runner + args: + API_URL: ${API_URL:-https://api.quyoshli.uz/api} + image: getgreen-uz:latest + container_name: getgreen-uz + restart: unless-stopped + ports: + - "${PORT:-3000}:3000" + environment: + NODE_ENV: production + API_URL: ${API_URL:-https://api.quyoshli.uz/api} + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:3000/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 15s diff --git a/next.config.ts b/next.config.ts index c2f8f9c..ef8725a 100644 --- a/next.config.ts +++ b/next.config.ts @@ -2,6 +2,7 @@ import type { NextConfig } from "next"; import createNextIntlPlugin from "next-intl/plugin" const nextConfig: NextConfig = { + output: "standalone", images:{ remotePatterns: [ {