- Published
Deploy a Next.js App to VPS Using Docker
- Authors
- Name
- Idhamsyah
- @Syahdham
3 min read
Deploying a Next.js app to a VPS might sound intimidating, especially if you're new to Docker or server-side deployment. This tutorial walks you through deploying a Next.js app to a VPS using Docker in a clean and scalable way.
What We'll Build
- Ubuntu-based VPS (e.g., DigitalOcean, Linode)
- Docker and Docker Compose for deployment
- Optional: Traefik as a reverse proxy. You can read previous article about Set up Traefik
- Your own domain (e.g.,
myportfolio.com
) - Free HTTPS with Let's Encrypt
- No database (for static/SPA apps)
Requirements
Make sure you have:
- A running VPS with SSH access
- A domain you control
- Next.js app ready to deploy
- Docker and Docker Compose installed on your VPS
If not yet, install Docker:
sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com | sh
sudo apt install docker-compose-plugin
docker -v
docker compose version
Directory Structure
/var/www/└── my-nextjs-app/ ├── docker-compose.yml ├── .env └── app/
1. Prepare Your Next.js Code
Create or copy your Next.js project:
npx create-next-app@latest app
Upload to VPS:
scp -r app/ root@your-vps-ip:/var/www/my-nextjs-app/app
2. Create Dockerfile
In /var/www/my-nextjs-app/app
:
FROM node:18-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm install
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
EXPOSE 3000
CMD ["npm", "start"]
docker-compose.yml
3. Create version: '3.8'
services:
nextjs:
container_name: my-nextjs-app
build:
context: ./app
dockerfile: Dockerfile
restart: always
ports:
- '3000:3000'
environment:
- NODE_ENV=production
networks:
- default
4. Run the App
cd /var/www/my-nextjs-app
docker compose up -d --build
Access via: http://your-vps-ip:3000
5. Point Your Domain
In your domain DNS:
A @ your-vps-ip
6. (Optional) Add Traefik Reverse Proxy + SSL
a. Folder structure
/var/www/traefik/├── traefik.yml├── docker-compose.yml└── acme.json
traefik.yml
b. api:
dashboard: true
entryPoints:
web:
address: ':80'
websecure:
address: ':443'
certificatesResolvers:
letsencrypt:
acme:
email: you@example.com
storage: acme.json
httpChallenge:
entryPoint: web
docker-compose.yml
c. version: '3.8'
services:
traefik:
image: traefik:v3.0
container_name: traefik
command:
- --configFile=/etc/traefik/traefik.yml
ports:
- '80:80'
- '443:443'
volumes:
- ./traefik.yml:/etc/traefik/traefik.yml
- ./acme.json:/acme.json
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
networks:
proxy:
external: true
d. Start Traefik
touch acme.json
chmod 600 acme.json
docker compose up -d
e. Add labels to your Next.js app:
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.my-nextjs-app.rule=Host(`mydomain.com`)'
- 'traefik.http.routers.my-nextjs-app.entrypoints=websecure'
- 'traefik.http.routers.my-nextjs-app.tls.certresolver=letsencrypt'
7. Restart and Access
docker compose up -d --build
Visit: https://mydomain.com
With this setup, you have a solid and scalable foundation to deploy your Next.js apps in production — ready to grow with your future projects.