I will go trough installing a nextjs app on your own ubuntu machine using docker, docker-compose and haproxy.
With this method you can have multiple nextjs apps on a single machine, haproxy will take care of mapping each domain against correct nextjs app.
As a prereq install docker, docker-compose and haproxy on your ubuntu machine.
In your next app directory place the following files:
docker-compose.yml
version: "3"
services:
appname:
build:
context: .
dockerfile: Dockerfile
container_name: app-name
restart: always
ports:
- "3000:3000"
Dockerfile
# Install dependencies only when needed
FROM node:alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
# Rebuild the source code only when needed
FROM node:alpine AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build
# Production image, copy all the files and run next
FROM node:alpine AS runner
WORKDIR /app
ENV NODE_ENV production
# You only need to copy next.config.js if you are NOT using the default configuration
# COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
RUN chown -R nextjs:nodejs /app/.next
USER nextjs
EXPOSE 3000
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry.
# RUN npx next telemetry disable
CMD ["node_modules/.bin/next", "start"]
Now you can start your next-app on port 3000 like this:
sudo docker-compose up -d --build
The haproxy setup
Lets edit /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend http-in
bind *:80
acl my-app-acl hdr(host) -i my-app.com
use_backend my-app if my-app-acl
default_backend my-app
backend my-app
server my-app 127.0.0.1:3000
We setup one app here called my-app against the domain my-app.com. The backend config for my-app runs on port 3000.
If you want more apps, run the next app on port 3001 an so fourth.