I'm following the instructions on Next.js' documentation to start the server using Docker: https://nextjs.org/docs/deployment#docker-image
Loading the site with http works but https returns SSL protocol errors.
What I did in detail:
Configured NGINX and cerbot (note that the guide is for Ubuntu 20) https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal on my DigitalOcean Ubuntu 22.4 server
Copied Dockerfile and .dockerignore from the example project linked in the docs to my project: https://github.com/vercel/next.js/tree/canary/examples/with-docker
Built and uploaded the image to the server.
Started the image on the server: docker run -p 80:3000 -p 443:3000 my_image
HTTP works perfectly (https://mysite.mydomain). With HTTPS I get errors, e.g. ERR_SSL_PROTOCOL_ERROR on Chrome and SSL_ERROR_RX_RECORD_TOO_LONG on Firefox.
Any ideas?
The following steps explain how to set up a multi-container Docker Compose environment where NGINX is used as a reverse proxy in front of the Next.js application to handle the SSL connection (and offer an HTTPS URI).
Luckily, this is part of the Next.js official docs themselves. The key step is to copy this Dockerfile to the Next.js repo you are working on.
Gotchas:
output: 'standalone' in next.config.js (like this)Dockerfile (3000 by default) is not what will be externally exposed; there's no need to expose that port publiclydocker build -t nextjs:latest -f Dockerfile .The Docker Compose environment will have two running containers: the Next.js app and NGINX.
The NGINX image can be created by adding a second Dockerfile:
# nginx/Dockerfile
FROM nginx:1.23.3-alpine
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 443
Build the image from the project root dir with docker build -t nginx:latest -f nginx/Dockerfile nginx.
Then, we can create a docker-compose.yml file:
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
Gotchas:
nginx.conf can be added for now, it'll be configured in the next step/etc/ssl. An alternative would be to pack them in the NGINX image (e.g. add COPY my_ssl_cert.crt /etc/nginx/ssl/my_ssl_cert.crt to the Dockerfile, idem for the key)Example nginx.conf:
# nginx/nginx.conf
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";
}
}
}
Gotchas:
nextjs because by default Compose sets up a single network for your app (docs)docker-compose.yml to the serverdocker compose updocker logs [container_name] to debug any issues; curl http://localhost:80 and curl --insecure https://localhost:443 can also helpIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With