From 7e900e0ece75875a83d396ee213a97d1a67e0693 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:28:44 +0000 Subject: [PATCH 1/4] Initial plan From fc4b26921eb826095e8c54c839ea424da06ebc10 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:35:13 +0000 Subject: [PATCH 2/4] Setup Docker deployment with nginx for pphat-first-docker.stackdev.cloud Co-authored-by: pphatdev <65520537+pphatdev@users.noreply.github.com> --- .dockerignore | 54 ++++++++++++++++++++++++++++ Dockerfile | 46 ++++++++++++++++++++++++ docker-compose.yml | 34 ++++++++++++++++++ next.config.ts | 1 + nginx/conf.d/default.conf | 75 +++++++++++++++++++++++++++++++++++++++ nginx/nginx.conf | 41 +++++++++++++++++++++ readme.md | 49 +++++++++++++++++++++++++ 7 files changed, 300 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 nginx/conf.d/default.conf create mode 100644 nginx/nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..05e7a92 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,54 @@ +# Dependencies +node_modules +.pnp +.pnp.js + +# Testing +coverage + +# Next.js build outputs +.next +out +build + +# Production +dist + +# Misc +.DS_Store +*.pem +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# IDE +.idea +.vscode +*.swp +*.swo + +# Git +.git +.gitignore + +# Docker +Dockerfile* +docker-compose* + +# Documentation +*.md + +# Vercel +.vercel + +# TypeScript +*.tsbuildinfo +next-env.d.ts diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c5f0f47 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# Multi-stage build for Next.js application +# Stage 1: Dependencies +FROM node:20-alpine AS deps +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json package-lock.json* ./ +RUN npm ci --only=production + +# Stage 2: Builder +FROM node:20-alpine AS builder +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Set environment variables for build +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +RUN npm run build + +# Stage 3: Runner +FROM node:20-alpine AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +# Create a non-root user +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy built assets +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 + +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +CMD ["node", "server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..17f010f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,34 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile + container_name: pphat-nextjs-app + restart: unless-stopped + environment: + - NODE_ENV=production + env_file: + - .env + networks: + - webnet + expose: + - "3000" + + nginx: + image: nginx:alpine + container_name: pphat-nginx + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/conf.d:/etc/nginx/conf.d:ro + depends_on: + - app + networks: + - webnet + +networks: + webnet: + driver: bridge diff --git a/next.config.ts b/next.config.ts index 81c097a..151070a 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,6 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { + output: "standalone", images: { remotePatterns: [ { diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/default.conf new file mode 100644 index 0000000..c2da61a --- /dev/null +++ b/nginx/conf.d/default.conf @@ -0,0 +1,75 @@ +# Upstream configuration for Next.js application +upstream nextjs_upstream { + server app:3000; + keepalive 64; +} + +# HTTP Server - Redirect to HTTPS (uncomment when SSL is configured) +# server { +# listen 80; +# listen [::]:80; +# server_name pphat-first-docker.stackdev.cloud; +# +# location / { +# return 301 https://$server_name$request_uri; +# } +# } + +# Main server block +server { + listen 80; + listen [::]:80; + server_name pphat-first-docker.stackdev.cloud; + + # Uncomment below and comment above when SSL is configured + # listen 443 ssl http2; + # listen [::]:443 ssl http2; + + # SSL Configuration (uncomment when certificates are available) + # ssl_certificate /etc/nginx/ssl/fullchain.pem; + # ssl_certificate_key /etc/nginx/ssl/privkey.pem; + # ssl_session_timeout 1d; + # ssl_session_cache shared:SSL:50m; + # ssl_session_tickets off; + # ssl_protocols TLSv1.2 TLSv1.3; + # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + # ssl_prefer_server_ciphers off; + + # Proxy settings + location / { + proxy_pass http://nextjs_upstream; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_cache_bypass $http_upgrade; + proxy_read_timeout 86400; + } + + # Static files caching + location /_next/static { + proxy_pass http://nextjs_upstream; + proxy_http_version 1.1; + proxy_set_header Host $host; + add_header Cache-Control "public, max-age=31536000, immutable"; + } + + # Public assets + location /assets { + proxy_pass http://nextjs_upstream; + proxy_http_version 1.1; + proxy_set_header Host $host; + add_header Cache-Control "public, max-age=86400"; + } + + # Health check endpoint + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } +} diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..0fac403 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,41 @@ +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Include additional configuration files + include /etc/nginx/conf.d/*.conf; +} diff --git a/readme.md b/readme.md index ed14ad7..e27de71 100644 --- a/readme.md +++ b/readme.md @@ -46,6 +46,55 @@ This command will: - Create an optimized production build - Start the production server +## 🐳 Docker Deployment + +This project includes Docker configuration for containerized deployment with nginx as a reverse proxy. + +### Prerequisites for Docker + +- **Docker** (version 20.10 or higher) +- **Docker Compose** (version 2.0 or higher) + +### Quick Start with Docker + +1. Copy the environment file: +```shell +cp .env.example .env +``` + +2. Build and start the containers: +```shell +docker compose up -d --build +``` + +3. Access the application at `http://pphat-first-docker.stackdev.cloud` (ensure DNS is configured) + +### Docker Commands + +```shell +# Build and start containers +docker compose up -d --build + +# View logs +docker compose logs -f + +# Stop containers +docker compose down + +# Rebuild and restart +docker compose up -d --build --force-recreate +``` + +### Configuration + +- **Dockerfile**: Multi-stage build for optimized Next.js production image +- **docker-compose.yml**: Orchestrates the Next.js app and nginx services +- **nginx/conf.d/default.conf**: nginx configuration with `server_name pphat-first-docker.stackdev.cloud` + +### SSL Configuration + +To enable HTTPS, uncomment the SSL configuration in `nginx/conf.d/default.conf` and mount your SSL certificates. + --- **💡 Quick Tip:** The development server includes TypeScript type checking and React Fast Refresh for an improved developer experience. From 47313b24cc6e22799203426dfa6308859893effb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 06:49:09 +0000 Subject: [PATCH 3/4] Rename nginx config and SSL dir to match project name Co-authored-by: pphatdev <65520537+pphatdev@users.noreply.github.com> --- docker-compose.yml | 1 + ...=> pphat-first-docker.stackdev.cloud.conf} | 4 ++-- .../README.md | 20 +++++++++++++++++++ readme.md | 7 +++++-- 4 files changed, 28 insertions(+), 4 deletions(-) rename nginx/conf.d/{default.conf => pphat-first-docker.stackdev.cloud.conf} (92%) create mode 100644 nginx/ssl/pphat-first-docker.stackdev.cloud/README.md diff --git a/docker-compose.yml b/docker-compose.yml index 17f010f..43d66b0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,7 @@ services: volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro + - ./nginx/ssl/pphat-first-docker.stackdev.cloud:/etc/nginx/ssl/pphat-first-docker.stackdev.cloud:ro depends_on: - app networks: diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/pphat-first-docker.stackdev.cloud.conf similarity index 92% rename from nginx/conf.d/default.conf rename to nginx/conf.d/pphat-first-docker.stackdev.cloud.conf index c2da61a..51c5df2 100644 --- a/nginx/conf.d/default.conf +++ b/nginx/conf.d/pphat-first-docker.stackdev.cloud.conf @@ -26,8 +26,8 @@ server { # listen [::]:443 ssl http2; # SSL Configuration (uncomment when certificates are available) - # ssl_certificate /etc/nginx/ssl/fullchain.pem; - # ssl_certificate_key /etc/nginx/ssl/privkey.pem; + # ssl_certificate /etc/nginx/ssl/pphat-first-docker.stackdev.cloud/fullchain.pem; + # ssl_certificate_key /etc/nginx/ssl/pphat-first-docker.stackdev.cloud/privkey.pem; # ssl_session_timeout 1d; # ssl_session_cache shared:SSL:50m; # ssl_session_tickets off; diff --git a/nginx/ssl/pphat-first-docker.stackdev.cloud/README.md b/nginx/ssl/pphat-first-docker.stackdev.cloud/README.md new file mode 100644 index 0000000..39d1486 --- /dev/null +++ b/nginx/ssl/pphat-first-docker.stackdev.cloud/README.md @@ -0,0 +1,20 @@ +# SSL Certificates Directory + +Place your SSL certificates here: +- `fullchain.pem` - Full certificate chain +- `privkey.pem` - Private key + +## Obtaining Certificates + +You can use Let's Encrypt with Certbot: + +```bash +certbot certonly --webroot -w /var/www/html -d pphat-first-docker.stackdev.cloud +``` + +Or use your preferred SSL certificate provider. + +## After Adding Certificates + +1. Uncomment the SSL configuration in `nginx/conf.d/pphat-first-docker.stackdev.cloud.conf` +2. Restart the nginx container: `docker compose restart nginx` diff --git a/readme.md b/readme.md index e27de71..c874b0f 100644 --- a/readme.md +++ b/readme.md @@ -89,11 +89,14 @@ docker compose up -d --build --force-recreate - **Dockerfile**: Multi-stage build for optimized Next.js production image - **docker-compose.yml**: Orchestrates the Next.js app and nginx services -- **nginx/conf.d/default.conf**: nginx configuration with `server_name pphat-first-docker.stackdev.cloud` +- **nginx/conf.d/pphat-first-docker.stackdev.cloud.conf**: nginx configuration with `server_name pphat-first-docker.stackdev.cloud` ### SSL Configuration -To enable HTTPS, uncomment the SSL configuration in `nginx/conf.d/default.conf` and mount your SSL certificates. +To enable HTTPS: +1. Add your SSL certificates to `nginx/ssl/pphat-first-docker.stackdev.cloud/` +2. Uncomment the SSL configuration in `nginx/conf.d/pphat-first-docker.stackdev.cloud.conf` +3. Restart the nginx container --- From 1c16981ee763c5a57ae900bf6b4b814af96fe6ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 07:17:10 +0000 Subject: [PATCH 4/4] Update domain from pphat-first-docker.stackdev.cloud to v4.stackdev.cloud Co-authored-by: pphatdev <65520537+pphatdev@users.noreply.github.com> --- docker-compose.yml | 2 +- ...-docker.stackdev.cloud.conf => v4.stackdev.cloud.conf} | 8 ++++---- .../README.md | 4 ++-- readme.md | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) rename nginx/conf.d/{pphat-first-docker.stackdev.cloud.conf => v4.stackdev.cloud.conf} (88%) rename nginx/ssl/{pphat-first-docker.stackdev.cloud => v4.stackdev.cloud}/README.md (67%) diff --git a/docker-compose.yml b/docker-compose.yml index 43d66b0..e1d5099 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro - - ./nginx/ssl/pphat-first-docker.stackdev.cloud:/etc/nginx/ssl/pphat-first-docker.stackdev.cloud:ro + - ./nginx/ssl/v4.stackdev.cloud:/etc/nginx/ssl/v4.stackdev.cloud:ro depends_on: - app networks: diff --git a/nginx/conf.d/pphat-first-docker.stackdev.cloud.conf b/nginx/conf.d/v4.stackdev.cloud.conf similarity index 88% rename from nginx/conf.d/pphat-first-docker.stackdev.cloud.conf rename to nginx/conf.d/v4.stackdev.cloud.conf index 51c5df2..048b8cb 100644 --- a/nginx/conf.d/pphat-first-docker.stackdev.cloud.conf +++ b/nginx/conf.d/v4.stackdev.cloud.conf @@ -8,7 +8,7 @@ upstream nextjs_upstream { # server { # listen 80; # listen [::]:80; -# server_name pphat-first-docker.stackdev.cloud; +# server_name v4.stackdev.cloud; # # location / { # return 301 https://$server_name$request_uri; @@ -19,15 +19,15 @@ upstream nextjs_upstream { server { listen 80; listen [::]:80; - server_name pphat-first-docker.stackdev.cloud; + server_name v4.stackdev.cloud; # Uncomment below and comment above when SSL is configured # listen 443 ssl http2; # listen [::]:443 ssl http2; # SSL Configuration (uncomment when certificates are available) - # ssl_certificate /etc/nginx/ssl/pphat-first-docker.stackdev.cloud/fullchain.pem; - # ssl_certificate_key /etc/nginx/ssl/pphat-first-docker.stackdev.cloud/privkey.pem; + # ssl_certificate /etc/nginx/ssl/v4.stackdev.cloud/fullchain.pem; + # ssl_certificate_key /etc/nginx/ssl/v4.stackdev.cloud/privkey.pem; # ssl_session_timeout 1d; # ssl_session_cache shared:SSL:50m; # ssl_session_tickets off; diff --git a/nginx/ssl/pphat-first-docker.stackdev.cloud/README.md b/nginx/ssl/v4.stackdev.cloud/README.md similarity index 67% rename from nginx/ssl/pphat-first-docker.stackdev.cloud/README.md rename to nginx/ssl/v4.stackdev.cloud/README.md index 39d1486..dc7b189 100644 --- a/nginx/ssl/pphat-first-docker.stackdev.cloud/README.md +++ b/nginx/ssl/v4.stackdev.cloud/README.md @@ -9,12 +9,12 @@ Place your SSL certificates here: You can use Let's Encrypt with Certbot: ```bash -certbot certonly --webroot -w /var/www/html -d pphat-first-docker.stackdev.cloud +certbot certonly --webroot -w /var/www/html -d v4.stackdev.cloud ``` Or use your preferred SSL certificate provider. ## After Adding Certificates -1. Uncomment the SSL configuration in `nginx/conf.d/pphat-first-docker.stackdev.cloud.conf` +1. Uncomment the SSL configuration in `nginx/conf.d/v4.stackdev.cloud.conf` 2. Restart the nginx container: `docker compose restart nginx` diff --git a/readme.md b/readme.md index c874b0f..a6790ee 100644 --- a/readme.md +++ b/readme.md @@ -67,7 +67,7 @@ cp .env.example .env docker compose up -d --build ``` -3. Access the application at `http://pphat-first-docker.stackdev.cloud` (ensure DNS is configured) +3. Access the application at `http://v4.stackdev.cloud` (ensure DNS is configured) ### Docker Commands @@ -89,13 +89,13 @@ docker compose up -d --build --force-recreate - **Dockerfile**: Multi-stage build for optimized Next.js production image - **docker-compose.yml**: Orchestrates the Next.js app and nginx services -- **nginx/conf.d/pphat-first-docker.stackdev.cloud.conf**: nginx configuration with `server_name pphat-first-docker.stackdev.cloud` +- **nginx/conf.d/v4.stackdev.cloud.conf**: nginx configuration with `server_name v4.stackdev.cloud` ### SSL Configuration To enable HTTPS: -1. Add your SSL certificates to `nginx/ssl/pphat-first-docker.stackdev.cloud/` -2. Uncomment the SSL configuration in `nginx/conf.d/pphat-first-docker.stackdev.cloud.conf` +1. Add your SSL certificates to `nginx/ssl/v4.stackdev.cloud/` +2. Uncomment the SSL configuration in `nginx/conf.d/v4.stackdev.cloud.conf` 3. Restart the nginx container ---