Deploy Nextjs on Docker with haproxy on ubuntu

Deploy Nextjs on Docker with haproxy on ubuntu

Posted on by Petter Kjelkenes - last updated 19. March, 2021

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:


version: "3"

      context: .
      dockerfile: Dockerfile
    container_name: app-name
    restart: always
      - "3000:3000"


# Install dependencies only when needed
FROM node:alpine AS deps
# Check to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
COPY package.json package-lock.json ./
RUN npm install

# Rebuild the source code only when needed
FROM node:alpine AS builder
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

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


# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here:
# 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

	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

	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
   use_backend my-app if my-app-acl

   default_backend my-app

backend my-app
   server my-app

We setup one app here called my-app against the domain 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.