From a2f80dd23f530d94b2333be3a50cfa5131fb97d9 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 20 Nov 2025 22:51:41 +0100 Subject: [PATCH] fix: convert Portainer stack to Docker Swarm mode with deploy labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - Moved all Traefik labels from root level to deploy.labels for Swarm compatibility - Added deploy.restart_policy to backend, frontend, and MinIO services - Removed restart: unless-stopped (incompatible with Swarm mode) - Keeps depends_on for startup ordering This fixes Gateway Timeout errors by ensuring Traefik can properly discover and route to services when running in Docker Swarm mode. Services updated: - xpeditis-backend: Deploy labels + restart policy - xpeditis-frontend: Deploy labels + restart policy - xpeditis-minio: Deploy labels + restart policy 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docker/portainer-stack.yml | 207 ++++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 96 deletions(-) diff --git a/docker/portainer-stack.yml b/docker/portainer-stack.yml index 50ea9d3..9cea867 100644 --- a/docker/portainer-stack.yml +++ b/docker/portainer-stack.yml @@ -40,7 +40,6 @@ services: # MinIO S3 Storage xpeditis-minio: image: minio/minio:latest - restart: unless-stopped command: server /data --console-address ":9001" volumes: - xpeditis_minio_data:/data @@ -56,62 +55,67 @@ services: timeout: 10s retries: 3 start_period: 20s - labels: - - "traefik.enable=true" - - "traefik.docker.network=traefik_network" + deploy: + restart_policy: + condition: any + delay: 5s + max_attempts: 3 + window: 120s + labels: + - "traefik.enable=true" + - "traefik.docker.network=traefik_network" - # MinIO API (S3) - HTTPS - - "traefik.http.routers.xpeditis-minio-api.rule=Host(`s3.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-minio-api.entrypoints=websecure" - - "traefik.http.routers.xpeditis-minio-api.tls=true" - - "traefik.http.routers.xpeditis-minio-api.tls.certresolver=letsencrypt" - - "traefik.http.routers.xpeditis-minio-api.priority=50" - - "traefik.http.routers.xpeditis-minio-api.service=xpeditis-minio-api" - - "traefik.http.services.xpeditis-minio-api.loadbalancer.server.port=9000" - - "traefik.http.routers.xpeditis-minio-api.middlewares=xpeditis-minio-api-headers" + # MinIO API (S3) - HTTPS + - "traefik.http.routers.xpeditis-minio-api.rule=Host(`s3.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-minio-api.entrypoints=websecure" + - "traefik.http.routers.xpeditis-minio-api.tls=true" + - "traefik.http.routers.xpeditis-minio-api.tls.certresolver=letsencrypt" + - "traefik.http.routers.xpeditis-minio-api.priority=50" + - "traefik.http.routers.xpeditis-minio-api.service=xpeditis-minio-api" + - "traefik.http.services.xpeditis-minio-api.loadbalancer.server.port=9000" + - "traefik.http.routers.xpeditis-minio-api.middlewares=xpeditis-minio-api-headers" - # MinIO API Headers - - "traefik.http.middlewares.xpeditis-minio-api-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" - - "traefik.http.middlewares.xpeditis-minio-api-headers.headers.customRequestHeaders.X-Forwarded-For=" - - "traefik.http.middlewares.xpeditis-minio-api-headers.headers.customRequestHeaders.X-Real-IP=" + # MinIO API Headers + - "traefik.http.middlewares.xpeditis-minio-api-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.http.middlewares.xpeditis-minio-api-headers.headers.customRequestHeaders.X-Forwarded-For=" + - "traefik.http.middlewares.xpeditis-minio-api-headers.headers.customRequestHeaders.X-Real-IP=" - # MinIO API - HTTP → HTTPS Redirect - - "traefik.http.routers.xpeditis-minio-api-http.rule=Host(`s3.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-minio-api-http.entrypoints=web" - - "traefik.http.routers.xpeditis-minio-api-http.priority=50" - - "traefik.http.routers.xpeditis-minio-api-http.middlewares=xpeditis-minio-api-redirect" - - "traefik.http.routers.xpeditis-minio-api-http.service=xpeditis-minio-api" - - "traefik.http.middlewares.xpeditis-minio-api-redirect.redirectscheme.scheme=https" - - "traefik.http.middlewares.xpeditis-minio-api-redirect.redirectscheme.permanent=true" + # MinIO API - HTTP → HTTPS Redirect + - "traefik.http.routers.xpeditis-minio-api-http.rule=Host(`s3.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-minio-api-http.entrypoints=web" + - "traefik.http.routers.xpeditis-minio-api-http.priority=50" + - "traefik.http.routers.xpeditis-minio-api-http.middlewares=xpeditis-minio-api-redirect" + - "traefik.http.routers.xpeditis-minio-api-http.service=xpeditis-minio-api" + - "traefik.http.middlewares.xpeditis-minio-api-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.xpeditis-minio-api-redirect.redirectscheme.permanent=true" - # MinIO Console - HTTPS - - "traefik.http.routers.xpeditis-minio-console.rule=Host(`minio.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-minio-console.entrypoints=websecure" - - "traefik.http.routers.xpeditis-minio-console.tls=true" - - "traefik.http.routers.xpeditis-minio-console.tls.certresolver=letsencrypt" - - "traefik.http.routers.xpeditis-minio-console.priority=50" - - "traefik.http.routers.xpeditis-minio-console.service=xpeditis-minio-console" - - "traefik.http.services.xpeditis-minio-console.loadbalancer.server.port=9001" - - "traefik.http.routers.xpeditis-minio-console.middlewares=xpeditis-minio-console-headers" + # MinIO Console - HTTPS + - "traefik.http.routers.xpeditis-minio-console.rule=Host(`minio.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-minio-console.entrypoints=websecure" + - "traefik.http.routers.xpeditis-minio-console.tls=true" + - "traefik.http.routers.xpeditis-minio-console.tls.certresolver=letsencrypt" + - "traefik.http.routers.xpeditis-minio-console.priority=50" + - "traefik.http.routers.xpeditis-minio-console.service=xpeditis-minio-console" + - "traefik.http.services.xpeditis-minio-console.loadbalancer.server.port=9001" + - "traefik.http.routers.xpeditis-minio-console.middlewares=xpeditis-minio-console-headers" - # MinIO Console Headers - - "traefik.http.middlewares.xpeditis-minio-console-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" - - "traefik.http.middlewares.xpeditis-minio-console-headers.headers.customRequestHeaders.X-Forwarded-For=" - - "traefik.http.middlewares.xpeditis-minio-console-headers.headers.customRequestHeaders.X-Real-IP=" + # MinIO Console Headers + - "traefik.http.middlewares.xpeditis-minio-console-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.http.middlewares.xpeditis-minio-console-headers.headers.customRequestHeaders.X-Forwarded-For=" + - "traefik.http.middlewares.xpeditis-minio-console-headers.headers.customRequestHeaders.X-Real-IP=" - # MinIO Console - HTTP → HTTPS Redirect - - "traefik.http.routers.xpeditis-minio-console-http.rule=Host(`minio.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-minio-console-http.entrypoints=web" - - "traefik.http.routers.xpeditis-minio-console-http.priority=50" - - "traefik.http.routers.xpeditis-minio-console-http.middlewares=xpeditis-minio-console-redirect" - - "traefik.http.routers.xpeditis-minio-console-http.service=xpeditis-minio-console" - - "traefik.http.middlewares.xpeditis-minio-console-redirect.redirectscheme.scheme=https" - - "traefik.http.middlewares.xpeditis-minio-console-redirect.redirectscheme.permanent=true" + # MinIO Console - HTTP → HTTPS Redirect + - "traefik.http.routers.xpeditis-minio-console-http.rule=Host(`minio.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-minio-console-http.entrypoints=web" + - "traefik.http.routers.xpeditis-minio-console-http.priority=50" + - "traefik.http.routers.xpeditis-minio-console-http.middlewares=xpeditis-minio-console-redirect" + - "traefik.http.routers.xpeditis-minio-console-http.service=xpeditis-minio-console" + - "traefik.http.middlewares.xpeditis-minio-console-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.xpeditis-minio-console-redirect.redirectscheme.permanent=true" # Backend API (NestJS) xpeditis-backend: image: rg.fr-par.scw.cloud/weworkstudio/xpeditis-backend:preprod - restart: unless-stopped depends_on: - xpeditis-db - xpeditis-redis @@ -174,38 +178,43 @@ services: retries: 3 start_period: 60s - labels: - - "traefik.enable=true" - - "traefik.docker.network=traefik_network" + deploy: + restart_policy: + condition: any + delay: 5s + max_attempts: 3 + window: 120s + labels: + - "traefik.enable=true" + - "traefik.docker.network=traefik_network" - # Backend API - HTTPS - - "traefik.http.routers.xpeditis-api.rule=Host(`api.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-api.entrypoints=websecure" - - "traefik.http.routers.xpeditis-api.tls=true" - - "traefik.http.routers.xpeditis-api.tls.certresolver=letsencrypt" - - "traefik.http.routers.xpeditis-api.priority=50" - - "traefik.http.routers.xpeditis-api.service=xpeditis-api" - - "traefik.http.services.xpeditis-api.loadbalancer.server.port=4000" - - "traefik.http.routers.xpeditis-api.middlewares=xpeditis-api-headers" + # Backend API - HTTPS + - "traefik.http.routers.xpeditis-api.rule=Host(`api.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-api.entrypoints=websecure" + - "traefik.http.routers.xpeditis-api.tls=true" + - "traefik.http.routers.xpeditis-api.tls.certresolver=letsencrypt" + - "traefik.http.routers.xpeditis-api.priority=50" + - "traefik.http.routers.xpeditis-api.service=xpeditis-api" + - "traefik.http.services.xpeditis-api.loadbalancer.server.port=4000" + - "traefik.http.routers.xpeditis-api.middlewares=xpeditis-api-headers" - # Backend API Headers - - "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" - - "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Forwarded-For=" - - "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Real-IP=" + # Backend API Headers + - "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Forwarded-For=" + - "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Real-IP=" - # Backend API - HTTP → HTTPS Redirect - - "traefik.http.routers.xpeditis-api-http.rule=Host(`api.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-api-http.entrypoints=web" - - "traefik.http.routers.xpeditis-api-http.priority=50" - - "traefik.http.routers.xpeditis-api-http.middlewares=xpeditis-api-redirect" - - "traefik.http.routers.xpeditis-api-http.service=xpeditis-api" - - "traefik.http.middlewares.xpeditis-api-redirect.redirectscheme.scheme=https" - - "traefik.http.middlewares.xpeditis-api-redirect.redirectscheme.permanent=true" + # Backend API - HTTP → HTTPS Redirect + - "traefik.http.routers.xpeditis-api-http.rule=Host(`api.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-api-http.entrypoints=web" + - "traefik.http.routers.xpeditis-api-http.priority=50" + - "traefik.http.routers.xpeditis-api-http.middlewares=xpeditis-api-redirect" + - "traefik.http.routers.xpeditis-api-http.service=xpeditis-api" + - "traefik.http.middlewares.xpeditis-api-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.xpeditis-api-redirect.redirectscheme.permanent=true" # Frontend (Next.js) xpeditis-frontend: image: rg.fr-par.scw.cloud/weworkstudio/xpeditis-frontend:preprod - restart: unless-stopped environment: NODE_ENV: production NEXT_PUBLIC_API_URL: https://api.preprod.xpeditis.com @@ -220,33 +229,39 @@ services: retries: 3 start_period: 40s - labels: - - "traefik.enable=true" - - "traefik.docker.network=traefik_network" + deploy: + restart_policy: + condition: any + delay: 5s + max_attempts: 3 + window: 120s + labels: + - "traefik.enable=true" + - "traefik.docker.network=traefik_network" - # Frontend - HTTPS - - "traefik.http.routers.xpeditis-app.rule=Host(`app.preprod.xpeditis.com`) || Host(`www.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-app.entrypoints=websecure" - - "traefik.http.routers.xpeditis-app.tls=true" - - "traefik.http.routers.xpeditis-app.tls.certresolver=letsencrypt" - - "traefik.http.routers.xpeditis-app.priority=50" - - "traefik.http.routers.xpeditis-app.service=xpeditis-app" - - "traefik.http.services.xpeditis-app.loadbalancer.server.port=3000" - - "traefik.http.routers.xpeditis-app.middlewares=xpeditis-app-headers" + # Frontend - HTTPS + - "traefik.http.routers.xpeditis-app.rule=Host(`app.preprod.xpeditis.com`) || Host(`www.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-app.entrypoints=websecure" + - "traefik.http.routers.xpeditis-app.tls=true" + - "traefik.http.routers.xpeditis-app.tls.certresolver=letsencrypt" + - "traefik.http.routers.xpeditis-app.priority=50" + - "traefik.http.routers.xpeditis-app.service=xpeditis-app" + - "traefik.http.services.xpeditis-app.loadbalancer.server.port=3000" + - "traefik.http.routers.xpeditis-app.middlewares=xpeditis-app-headers" - # Frontend Headers - - "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" - - "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Forwarded-For=" - - "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Real-IP=" + # Frontend Headers + - "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Forwarded-Proto=https" + - "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Forwarded-For=" + - "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Real-IP=" - # Frontend - HTTP → HTTPS Redirect - - "traefik.http.routers.xpeditis-app-http.rule=Host(`app.preprod.xpeditis.com`) || Host(`www.preprod.xpeditis.com`)" - - "traefik.http.routers.xpeditis-app-http.entrypoints=web" - - "traefik.http.routers.xpeditis-app-http.priority=50" - - "traefik.http.routers.xpeditis-app-http.middlewares=xpeditis-app-redirect" - - "traefik.http.routers.xpeditis-app-http.service=xpeditis-app" - - "traefik.http.middlewares.xpeditis-app-redirect.redirectscheme.scheme=https" - - "traefik.http.middlewares.xpeditis-app-redirect.redirectscheme.permanent=true" + # Frontend - HTTP → HTTPS Redirect + - "traefik.http.routers.xpeditis-app-http.rule=Host(`app.preprod.xpeditis.com`) || Host(`www.preprod.xpeditis.com`)" + - "traefik.http.routers.xpeditis-app-http.entrypoints=web" + - "traefik.http.routers.xpeditis-app-http.priority=50" + - "traefik.http.routers.xpeditis-app-http.middlewares=xpeditis-app-redirect" + - "traefik.http.routers.xpeditis-app-http.service=xpeditis-app" + - "traefik.http.middlewares.xpeditis-app-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.xpeditis-app-redirect.redirectscheme.permanent=true" volumes: xpeditis_db_data: