how to self-host next.js 16 with docker and sqlite - By Sourav Mishra (@souravvmishra)

save a ton of money by self-hosting next.js 16. here is a simple guide using docker, sqlite, and a basic vps.

BySourav Mishra3 min read

okeyy, let's talk about the "vercel tax". vercel is awesome, but it can get super expensive. the good news? self-hosting next.js 16 is now super easy thanks to its standalone output.

i am sourav mishra, and we use this exact strategy at codestam technologies to host our internal tools for pennies.


why self-host?

it's all about control and cost. a simple $5 vps can handle thousands of requests per second if you do it right. you really don't need a crazy expensive cloud setup for most things.


step 1: the dockerfile

the trick here is a multi-stage build. it keeps your docker image around 100mb instead of a massive 1gb.

# Dockerfile
FROM node:20-alpine AS base

FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000
CMD ["node", "server.js"]

don't forget to set output: 'standalone' in your next.config.mjs!


step 2: storing data in sqlite

you probably don't need postgres. sqlite (or turso/libsql) is insanely fast because it's just a file on your server.

at codestam technologies, we handled 50k+ requests a day on a single $5 vps using this setup.

// lib/db.ts
import Database from 'better-sqlite3';

const db = new Database('sqlite.db');
db.pragma('journal_mode = WAL');

export default db;

when you deploy, just mount a volume so your sqlite.db doesn't get deleted when docker restarts.


step 3: the docker-compose file

use docker-compose.yml to run the container and restart it if it crashes.

version: '3'
services:
  nextjs-app:
    build: .
    restart: always
    ports:
      - "3000:3000"
    volumes:
      - ./data:/app/data

step 4: setting up nginx

never expose node.js directly to the web. use nginx as a reverse proxy to handle ssl and forward traffic.

server {
    listen 80;
    server_name example.com;

    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_cache_bypass $http_upgrade;
    }
}

vercel vs self-hosting

FeatureVercelSelf-Hosted (Docker)
costfree tier, then gets pricey fastfixed like $5-$10/mo
setupalmost nothinggotta learn docker & nginx
scalingautomaticupgrade your vps
controlnot muchfull root access

wrapping up

self-hosting next.js 16 is a great choice if you want to save money. docker and sqlite make it super solid and you own the whole thing.

worried about seo? read my next.js seo guide.

wanna speed up your dev workflow? see why turbopack is amazing.


written by sourav mishra. building fast things at codestam technologies.

Share this post

Cover image for how to self-host next.js 16 with docker and sqlite

You might also like

See all