fix(nginx): add Docker DNS resolver for Swarm/dynamic service discovery

- Add resolver 127.0.0.11 directive for Docker's internal DNS
- Use variable-based proxy_pass to force per-request DNS resolution
- Fix 502 Bad Gateway error on root path in Docker Swarm deployments

The issue was that nginx caches DNS lookups at startup, but in Docker
Swarm where service IPs can change dynamically, this caused stale DNS
entries leading to 502 errors for proxied requests.

Bumps version to 2.2.3
This commit is contained in:
Paul Nothaft
2026-01-08 16:25:05 +01:00
parent 0ab8cbde7f
commit 049837f9d6
3 changed files with 22 additions and 11 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "picpeak-backend",
"version": "2.2.2",
"version": "2.2.3",
"description": "Backend for PicPeak event photo sharing platform",
"main": "server.js",
"scripts": {
+20 -9
View File
@@ -4,6 +4,10 @@ server {
root /usr/share/nginx/html;
index index.html;
# Docker DNS resolver for dynamic service discovery (required for Swarm/Compose)
resolver 127.0.0.11 valid=10s ipv6=off;
resolver_timeout 5s;
# Allow larger file uploads (up to 100MB)
client_max_body_size 100M;
client_body_timeout 300s;
@@ -43,7 +47,9 @@ server {
# API proxy
location /api {
proxy_pass http://backend:3000;
# Use variable to force DNS resolution per request (required for Docker Swarm)
set $backend_upstream backend;
proxy_pass http://$backend_upstream:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
@@ -53,7 +59,7 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 86400;
# Allow larger uploads for API endpoints
client_max_body_size 100M;
client_body_timeout 300s;
@@ -61,13 +67,14 @@ server {
# Photo serving proxy
location /photos {
proxy_pass http://backend:3000;
set $backend_upstream backend;
proxy_pass http://$backend_upstream:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Cache photos
proxy_cache_valid 200 302 1d;
proxy_cache_valid 404 1m;
@@ -75,13 +82,14 @@ server {
# Thumbnail serving proxy
location /thumbnails {
proxy_pass http://backend:3000;
set $backend_upstream backend;
proxy_pass http://$backend_upstream:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Cache thumbnails
proxy_cache_valid 200 302 7d;
proxy_cache_valid 404 1m;
@@ -90,13 +98,14 @@ server {
# Uploads serving proxy (logos, favicons, watermarks)
# ^~ modifier stops regex matching, ensuring uploads are proxied not served locally
location ^~ /uploads {
proxy_pass http://backend:3000;
set $backend_upstream backend;
proxy_pass http://$backend_upstream:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Cache uploads
proxy_cache_valid 200 302 7d;
proxy_cache_valid 404 1m;
@@ -104,7 +113,9 @@ server {
# Delegate root requests to backend for public landing page handling
location = / {
proxy_pass http://backend:3000/;
# Use variable to force DNS resolution per request (required for Docker Swarm)
set $backend_upstream backend;
proxy_pass http://$backend_upstream:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "picpeak-frontend",
"private": true,
"version": "2.2.2",
"version": "2.2.3",
"type": "module",
"scripts": {
"dev": "vite",