Securing your Next.js application with HTTPS is essential for production environments. This guide walks you through setting up a Docker Compose environment with Nginx as a reverse proxy to handle SSL connections for your Next.js application.
Step 1: Dockerize Your Next.js Application
First, you’ll need to containerize your Next.js application:
- Copy the official Next.js Dockerfile from the Next.js documentation to your project root.
- Add a
.dockerignore
file to exclude unnecessary files from your Docker image. - Configure your
next.config.js
to use standalone output:module.exports = { output: 'standalone' }
- Build your Next.js Docker image:
docker build -t nextjs:latest -f Dockerfile .
Note: We won’t expose port 3000 publicly since Nginx will handle external connections.
Step 2: Create the Nginx Container
Create a dedicated Dockerfile for Nginx in a separate directory:
FROM nginx:1.23.3-alpine
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 443
Build the Nginx image:
docker build -t nginx:latest -f nginx/Dockerfile nginx
Step 3: Set Up Docker Compose
Create a docker-compose.yml
file to orchestrate both containers:
version: "3.9"
services:
nextjs:
image: nextjs:latest
container_name: nextjs
ports:
- "3000:3000"
restart: always
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- /etc/ssl:/etc/nginx/ssl:ro
restart: always
Important Notes:
- Public ports 80 (HTTP) and 443 (HTTPS) need to be open on your server
- SSL certificates are mounted from the host machine’s
/etc/ssl
directory - Alternatively, you could include the certificates directly in your Nginx image
Step 4: Configure Nginx as a Reverse Proxy
Create an nginx.conf
file with the following configuration:
events { }
http {
upstream nextjs {
server nextjs:3000;
}
server {
# Redirect HTTP requests to HTTPS
listen 80;
server_name localhost;
root /srv/public;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name localhost;
root /srv/public;
server_tokens off;
ssl_certificate /etc/nginx/ssl/my_ssl_cert.crt;
ssl_certificate_key /etc/nginx/ssl/my_ssl_key.key;
location / {
try_files $uri $uri/ @nextjs;
}
location @nextjs {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://nextjs;
proxy_cookie_path / "/; HTTPOnly; Secure";
}
}
}
Note: Docker Compose automatically creates a network where containers can reference each other by their service names (like “nextjs”).
Step 5: Deployment
- Build both Docker images on your development machine
- Transfer the images, SSL certificates, and
docker-compose.yml
to your server - Run the application:
docker compose up -d
- Troubleshooting:
- Check container logs:
docker logs nginx
ordocker logs nextjs
- Test HTTP redirect:
curl http://localhost:80
- Test HTTPS connection:
curl --insecure https://localhost:443
- Check container logs:
Security Considerations
- Replace “localhost” with your actual domain name in the Nginx configuration
- Ensure your SSL certificates are properly secured
- Consider implementing additional security headers
- Set up automatic certificate renewal if using Let’s Encrypt
With this setup, your Next.js application will be accessible via HTTPS, with Nginx handling SSL termination and acting as a reverse proxy.