From 049837f9d675ff5a4d93c02e5eb771bf65bc2616 Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Thu, 8 Jan 2026 16:25:05 +0100 Subject: [PATCH] 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 --- backend/package.json | 2 +- frontend/nginx.conf | 29 ++++++++++++++++++++--------- frontend/package.json | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/backend/package.json b/backend/package.json index bb355010..e7d42584 100644 --- a/backend/package.json +++ b/backend/package.json @@ -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": { diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 4b04c6e6..348c669d 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -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'; diff --git a/frontend/package.json b/frontend/package.json index de401204..7bf177b0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "picpeak-frontend", "private": true, - "version": "2.2.2", + "version": "2.2.3", "type": "module", "scripts": { "dev": "vite",