Deploying a Next.js application to a VPS doesn’t have to be complicated. With Docker, you can containerize your app for consistent performance and easy scaling, while Bun improves dependency management. This guide breaks down the process into clear, actionable steps—from configuring Next.js for standalone output to setting up a reverse proxy with NGINX and securing HTTPS with Certbot. Follow along to ensure your application runs efficiently in production.
Configure Next.js for Standalone Output
Next.js offers a standalone output mode that generates a minimal production build, reducing deployment footprint. This mode excludes development dependencies and optimizes runtime performance. To enable it, update your next.config.ts with the following configuration:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
};
export default nextConfig;This setting instructs Next.js to bundle only what’s necessary for production, streamlining your Docker image. However, for real-world use, additional security and performance optimizations are essential.
Optimize Dockerfile for Bun and Next.js
A well-structured Dockerfile ensures fast builds and secure deployments. Start by splitting the build into multi-stage stages: one for installing dependencies, another for building the app, and a final stage for running the application. Here’s how to tailor it for Bun:
# Stage 1: Install dependencies with Bun
FROM oven/bun:1 AS dependencies
WORKDIR /app
COPY package.json bun.lock* ./
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --no-save --frozen-lockfile
# Stage 2: Build the Next.js application
FROM oven/bun:1 AS builder
WORKDIR /app
COPY --from=dependencies /app/node_modules ./node_modules
COPY . .
ENV NODE_ENV=production
RUN bun run build
# Stage 3: Run the application
FROM oven/bun:1 AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Copy only necessary files and set permissions
COPY --from=builder --chown=bun:bun /app/public ./public
RUN mkdir .next && chown bun:bun .next
COPY --from=builder --chown=bun:bun /app/.next/standalone ./
COPY --from=builder --chown=bun:bun /app/.next/static ./.next/static
# Run as non-root user for security
USER bun
EXPOSE 3000
CMD ["bun", "server.js"]Key optimizations include leveraging Docker’s caching for dependencies and using Bun’s --frozen-lockfile flag to ensure reproducible builds. The final stage runs as a non-root user to enhance security.
Set Up Docker Compose for Local Development and Deployment
Docker Compose simplifies managing multiple services, such as your Next.js app, NGINX, and Certbot for HTTPS. Below is a production-ready configuration:
services:
app:
build:
context: .
dockerfile: Dockerfile
image: nextjs-standalone-bun-image
container_name: nextjs-app
environment:
NODE_ENV: production
PORT: "3000"
HOSTNAME: "0.0.0.0"
expose:
- "3000"
restart: unless-stopped
networks:
- app-network
nginx:
image: nginx:stable-alpine
container_name: nginx-proxy
depends_on:
- app
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/nginx.conf:ro
- certbot_www:/var/www/certbot
- certbot_conf:/etc/letsencrypt
restart: unless-stopped
networks:
- app-network
certbot:
image: certbot/certbot:latest
container_name: certbot
volumes:
- certbot_www:/var/www/certbot
- certbot_conf:/etc/letsencrypt
entrypoint: >
sh -c 'trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --quiet; sleep 12h; done'
restart: unless-stopped
volumes:
certbot_www:
certbot_conf:
networks:
app-network:
driver: bridgeThis setup includes NGINX as a reverse proxy to handle routing and HTTPS termination, while Certbot automates certificate renewal. Adjust the default.conf for your domain’s SSL configuration.
Configure NGINX for Reverse Proxy and HTTPS
A basic NGINX configuration routes traffic to your Next.js app and enables HTTPS. Create a default.conf file in your nginx directory:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
return 301
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
server {
listen 443 ssl;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass
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;
}
}This configuration redirects HTTP traffic to HTTPS and proxies requests to your Next.js container. Ensure your domain’s DNS records point to your VPS IP address before proceeding.
Final Steps for Production Deployment
Before deploying, test your setup locally with Docker Compose:
# Build and start services
docker compose up --build
# Verify the Next.js app is running
curl
# Check NGINX and HTTPS configuration
curl -I For production, consider adding monitoring, logging, and backup strategies. Next.js’s standalone mode and Docker’s multi-stage builds provide a solid foundation, but continuous optimization is key to maintaining performance and security as your application grows.
The future of deployment lies in automation and scalability. By containerizing your Next.js app with Docker and Bun, you’re not just simplifying the process—you’re future-proofing your infrastructure for seamless updates and scaling.
AI summary
Next.js projelerinizi Docker ve VPS kullanarak nasıl verimli şekilde dağıtabilirsiniz? Standalone mod, Dockerfile optimizasyonu, NGINX ters proxy ve HTTPS ayarları hakkında adım adım rehber.
Tags