DeployWise
HomeDeploy Next.js Without Docker
Next.jsDockerPM2

How to Deploy a Next.js App to a VPS Without Docker

Docker is powerful — but for a single Next.js app on a $6 VPS, it's overkill. Learn the PM2 + Nginx stack that uses half the RAM, deploys in seconds, and is easier to debug.

Mar 9, 2026
10 min read

Why deploy Next.js without Docker?

Docker solves real problems — dependency isolation, reproducible builds, orchestration at scale. But when you're running a single Next.js app on a VPS, those problems don't exist yet. What you get instead is extra complexity and resource overhead on a machine that has neither to spare.

Lighter resource usage

No Docker daemon eating 100–200 MB of RAM. Your 1 GB VPS stays free for your actual app.

Faster deploys

Skip image builds entirely. A git pull + npm run build + pm2 reload takes 20–30 seconds.

Simpler debugging

Logs are in PM2, config is in Nginx. No container layers, no docker exec, no volume mounts to trace.

Lower overhead on cheap VPS

A $6 VPS with 1 GB RAM can comfortably run Next.js with PM2. Add Docker and you're already tight.

Docker vs PM2 + Nginx: side-by-side

Here's how the two approaches compare for a typical Next.js app on a single VPS:

MetricDockerPM2 + Nginx
RAM usage (idle)300–500 MB100–180 MB
Deploy speed2–5 min (image build)20–40 sec (git pull + build)
Setup complexityDockerfile, compose, networkingecosystem.config.js + Nginx conf
Debuggingdocker logs, exec, inspectpm2 logs, standard Linux tools
Cold start5–10 sec (container init)1–2 sec (process start)
Disk usage500 MB–1 GB+ (images + layers)100–200 MB (app + node_modules)

When Docker makes sense (and when it doesn't)

This isn't anti-Docker. Docker is excellent — for the right use cases. Here's a quick decision framework:

Use Docker when…
Running multiple apps with conflicting dependencies
Your team needs identical dev/prod environments
You use Kubernetes or container orchestration
Multi-service architectures (app + DB + cache + workers)
Enterprise compliance requires container isolation
Skip Docker when…
Single Next.js app on a single VPS
Budget VPS with 1–2 GB RAM
Solo developer or small team
You want fast, simple deploys
You value straightforward debugging

The PM2 + Nginx stack explained

Instead of Docker, you use two battle-tested tools that have been running Node.js apps in production for over a decade:

PM2
Process Manager
Keeps your Next.js process alive 24/7. If the app crashes at 3 AM, PM2 restarts it in milliseconds. It also handles log aggregation, memory limits, cluster mode, and zero-downtime reloads.
Nginx
Reverse Proxy + Web Server
Sits in front of your app on ports 80/443. Handles SSL termination, gzip compression, static file caching, and proxies requests to your Next.js process on port 3000.
Certbot
SSL Certificate Manager
Obtains and auto-renews free Let’s Encrypt SSL certificates. Integrates directly with Nginx — one command and your site is HTTPS.

The request flow: Client → Nginx (443) → PM2 → Next.js (3000)

Step-by-step: deploy Next.js to a VPS without Docker

This guide uses Ubuntu 22.04/24.04 on any VPS provider (Hetzner, DigitalOcean, Hostinger, etc.). The entire process takes about 15 minutes.

1. Server setup

Start with a fresh Ubuntu VPS. Create a non-root user and configure the firewall:

bash
# Create a deploy user
adduser deploy
usermod -aG sudo deploy

# Configure firewall
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable

# Switch to deploy user
su - deploy

Install Node.js via NVM:

bash
# Install NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc

# Install Node.js LTS
nvm install --lts
nvm use --lts

# Verify
node -v  # v22.x.x
npm -v   # 10.x.x

2. Clone and build your Next.js app

bash
# Clone your repo
git clone https://github.com/you/my-nextjs-app.git /var/www/my-app
cd /var/www/my-app

# Install production dependencies
npm ci

# Set environment variables
cp .env.example .env
nano .env  # add your production values

# Build for production
npm run build

3. PM2 ecosystem config

Create an ecosystem.config.js in your project root. This tells PM2 how to run your app:

javascript
module.exports = {
  apps: [
    {
      name: "my-nextjs-app",
      script: "node_modules/.bin/next",
      args: "start",
      cwd: "/var/www/my-app",
      instances: 1,
      autorestart: true,
      max_memory_restart: "512M",
      env: {
        NODE_ENV: "production",
        PORT: 3000,
      },
    },
  ],
};
bash
# Install PM2 globally
npm install -g pm2

# Start the app with PM2
pm2 start ecosystem.config.js
pm2 save

# Enable auto-start on server reboot
pm2 startup
# Run the command PM2 outputs

4. Nginx reverse proxy config

Install Nginx and create a server block that proxies traffic to your Next.js app:

bash
sudo apt update && sudo apt install -y nginx
nginx
# /etc/nginx/sites-available/my-app

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    # Gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;
    gzip_min_length 1000;

    location / {
        proxy_pass http://localhost:3000;
        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_cache_bypass $http_upgrade;
    }

    # Cache Next.js static assets
    location /_next/static {
        proxy_pass http://localhost:3000;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }
}
bash
# Enable the site
sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

5. SSL with Certbot

Get a free SSL certificate from Let's Encrypt. Certbot auto-configures Nginx for HTTPS:

bash
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx

# Obtain SSL certificate (auto-modifies Nginx config)
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Verify auto-renewal
sudo certbot renew --dry-run

6. Auto-deploy with GitHub webhooks

Create a simple webhook script so every push to main triggers a redeploy:

bash
#!/bin/bash
# /var/www/deploy.sh

cd /var/www/my-app
git pull origin main
npm ci
npm run build
pm2 reload my-nextjs-app

You can use a lightweight webhook server like webhook or a simple Express endpoint to trigger this script. Or — skip the scripting entirely and let DeployWise handle it.

Resource comparison on a $6 VPS (1 GB RAM)

Here's what a real Next.js app looks like on a budget VPS with and without Docker:

With Docker
Docker daemon~120 MB
Container overhead~80 MB
Next.js process~150 MB
Nginx (in container)~30 MB
Total~380 MB
Remaining for OS + cache~620 MB
Without Docker (PM2 + Nginx)
Docker daemon0 MB
Container overhead0 MB
Next.js process~130 MB
Nginx (native)~10 MB
Total~140 MB
Remaining for OS + cache~860 MB

That's 240 MB saved — a 63% reduction in memory usage. On a 1 GB VPS, that's the difference between comfortable headroom and OOM kills under load.

The automated way: DeployWise

Every step above — Node.js installation, PM2 config, Nginx reverse proxy, SSL, and GitHub webhook deploys — is exactly what DeployWise automates for you. No Docker required.

1.Sign in with GitHub, select your repo
2.Add your VPS (paste the IP, DeployWise sets up SSH)
3.Click Deploy — DeployWise installs Node.js, PM2, Nginx, SSL automatically
4.Every push to main triggers a zero-downtime redeploy
5.View logs, rollback, manage env vars from the dashboard

You get all the benefits of bare-metal performance (no Docker overhead) with the convenience of a managed platform. Free tier available.

Frequently asked questions

Can I deploy Next.js without Docker?

Yes. Next.js is a Node.js application at its core. You can run it directly on any Linux server using PM2 as a process manager and Nginx as a reverse proxy. No containers needed.

Is deploying without Docker less secure?

Not inherently. Docker adds isolation, but a properly configured VPS with firewall rules (UFW), non-root users, and regular updates is equally secure for most applications. Many production Node.js apps run without containers.

When should I use Docker instead of PM2 + Nginx?

Docker shines when you need reproducible environments across teams, run multiple apps with conflicting dependencies, or use orchestration tools like Kubernetes. For a single Next.js app on a VPS, PM2 + Nginx is simpler and uses fewer resources.

How much RAM does Next.js need without Docker?

A typical Next.js app uses 80-150 MB of RAM when running directly with PM2. The same app in a Docker container uses 200-400 MB due to the container runtime overhead. A $6 VPS with 1 GB RAM can comfortably run a Next.js app without Docker.

Can I still use GitHub Actions CI/CD without Docker?

Absolutely. You can set up GitHub webhooks or GitHub Actions to SSH into your VPS, pull the latest code, rebuild, and reload PM2 — all without Docker. DeployWise automates this entire workflow for you.

Deploy Next.js without Docker — in one click

DeployWise sets up PM2, Nginx, and SSL on your VPS automatically. No containers, no Dockerfile, no DevOps knowledge needed.

Deploy Now — Free

Related reading