@@ -57,6 +57,7 @@ services:
5757 - traefik.http.services.${SWARM_STACK_NAME}_api-server.loadbalancer.healthcheck.path=/
5858 - traefik.http.services.${SWARM_STACK_NAME}_api-server.loadbalancer.healthcheck.interval=2000ms
5959 - traefik.http.services.${SWARM_STACK_NAME}_api-server.loadbalancer.healthcheck.timeout=1000ms
60+ # NOTE: keep in sync with fallback router (rule and entrypoint)
6061 - traefik.http.routers.${SWARM_STACK_NAME}_api-server.rule=(Path(`/`) || Path(`/v0`) || PathPrefix(`/v0/`) || Path(`/api/v0/openapi.json`))
6162 - traefik.http.routers.${SWARM_STACK_NAME}_api-server.entrypoints=simcore_api
6263 - traefik.http.routers.${SWARM_STACK_NAME}_api-server.priority=3
@@ -628,6 +629,7 @@ services:
628629 - traefik.http.services.${SWARM_STACK_NAME}_static_webserver.loadbalancer.healthcheck.interval=2000ms
629630 - traefik.http.services.${SWARM_STACK_NAME}_static_webserver.loadbalancer.healthcheck.timeout=1000ms
630631 - traefik.http.middlewares.${SWARM_STACK_NAME}_static_webserver_retry.retry.attempts=2
632+ # NOTE: keep in sync with fallback router (rule and entrypoint)
631633 - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver.rule=(Path(`/osparc`) || Path(`/s4l`) || Path(`/s4llite`) || Path(`/s4lacad`) || Path(`/s4lengine`) || Path(`/s4ldesktop`) || Path(`/s4ldesktopacad`) || Path(`/tis`) || Path(`/tiplite`) || Path(`/transpiled`) || Path(`/resource`) || PathPrefix(`/osparc/`) || PathPrefix(`/s4l/`) || PathPrefix(`/s4llite/`) || PathPrefix(`/s4lacad/`) || PathPrefix(`/s4lengine/`) || PathPrefix(`/s4ldesktop/`) || PathPrefix(`/s4ldesktopacad/`) || PathPrefix(`/tis/`) || PathPrefix(`/tiplite/`) || PathPrefix(`/transpiled/`) || PathPrefix(`/resource/`))
632634 - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver.service=${SWARM_STACK_NAME}_static_webserver
633635 - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver.entrypoints=http
@@ -876,6 +878,7 @@ services:
876878 - traefik.http.services.${SWARM_STACK_NAME}_webserver.loadbalancer.sticky.cookie.secure=true
877879 - traefik.http.middlewares.${SWARM_STACK_NAME}_webserver_retry.retry.attempts=2
878880 - traefik.http.routers.${SWARM_STACK_NAME}_webserver.service=${SWARM_STACK_NAME}_webserver
881+ # NOTE: keep in sync with fallback router (rule and entrypoint)
879882 - traefik.http.routers.${SWARM_STACK_NAME}_webserver.rule=(Path(`/`) || Path(`/v0`) || Path(`/socket.io/`) || Path(`/static-frontend-data.json`) || PathRegexp(`^/study/(?P<study_uuid>\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b)`) || Path(`/view`) || Path(`/#/view`) || Path(`/#/error`) || PathPrefix(`/v0/`))
880883 - traefik.http.routers.${SWARM_STACK_NAME}_webserver.entrypoints=http
881884 - traefik.http.routers.${SWARM_STACK_NAME}_webserver.priority=6
@@ -1452,6 +1455,56 @@ services:
14521455 - default
14531456 - interactive_services_subnet # for legacy dynamic services
14541457
1458+ # use to define fallback routes for simcore services
1459+ # if docker healthcheck fails, container's traefik configuration is removed
1460+ # leading to 404 https://github.com/traefik/traefik/issues/7842
1461+ #
1462+ # use fallback routes to return proper 503 (instead of 404)
1463+ # this service must be running at all times
1464+ traefik-configuration-placeholder :
1465+ image : busybox:1.35.0
1466+ command : sleep infinity
1467+ networks :
1468+ - default
1469+ deploy :
1470+ labels :
1471+ # route to internal traefik
1472+ - traefik.enable=true
1473+ - io.simcore.zone=${TRAEFIK_SIMCORE_ZONE}
1474+
1475+ # ## Fallback for api-server
1476+ - traefik.http.routers.${SWARM_STACK_NAME}_api-server_fallback.rule=(Path(`/`) || Path(`/v0`) || PathPrefix(`/v0/`) || Path(`/api/v0/openapi.json`))
1477+ - traefik.http.routers.${SWARM_STACK_NAME}_api-server_fallback.service=${SWARM_STACK_NAME}_api-server_fallback
1478+ - traefik.http.routers.${SWARM_STACK_NAME}_api-server_fallback.entrypoints=simcore_api
1479+ - traefik.http.routers.${SWARM_STACK_NAME}_api-server_fallback.priority=1
1480+ # always fail and return 503 via unhealthy loadbalancer healthcheck
1481+ - traefik.http.services.${SWARM_STACK_NAME}_api-server_fallback.loadbalancer.server.port=0 # port is required (otherwise traefik service is not created)
1482+ - traefik.http.services.${SWARM_STACK_NAME}_api-server_fallback.loadbalancer.healthcheck.path=/some/invalid/path/to/generate/a/503
1483+ - traefik.http.services.${SWARM_STACK_NAME}_api-server_fallback.loadbalancer.healthcheck.interval=10s
1484+ - traefik.http.services.${SWARM_STACK_NAME}_api-server_fallback.loadbalancer.healthcheck.timeout=1ms
1485+
1486+ # ## Fallback for webserver
1487+ - traefik.http.routers.${SWARM_STACK_NAME}_webserver_fallback.service=${SWARM_STACK_NAME}_webserver_fallback
1488+ - traefik.http.routers.${SWARM_STACK_NAME}_webserver_fallback.rule=(Path(`/`) || Path(`/v0`) || Path(`/socket.io/`) || Path(`/static-frontend-data.json`) || PathRegexp(`^/study/(?P<study_uuid>\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b)`) || Path(`/view`) || Path(`/#/view`) || Path(`/#/error`) || PathPrefix(`/v0/`))
1489+ - traefik.http.routers.${SWARM_STACK_NAME}_webserver_fallback.entrypoints=http
1490+ - traefik.http.routers.${SWARM_STACK_NAME}_webserver_fallback.priority=1
1491+ # always fail and return 503 via unhealthy loadbalancer healthcheck
1492+ - traefik.http.services.${SWARM_STACK_NAME}_webserver_fallback.loadbalancer.server.port=0
1493+ - traefik.http.services.${SWARM_STACK_NAME}_webserver_fallback.loadbalancer.healthcheck.path=/v0/
1494+ - traefik.http.services.${SWARM_STACK_NAME}_webserver_fallback.loadbalancer.healthcheck.interval=10s
1495+ - traefik.http.services.${SWARM_STACK_NAME}_webserver_fallback.loadbalancer.healthcheck.timeout=1ms
1496+
1497+ # ## Fallback for static-webserver
1498+ - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver_fallback.rule=(Path(`/osparc`) || Path(`/s4l`) || Path(`/s4llite`) || Path(`/s4lacad`) || Path(`/s4lengine`) || Path(`/s4ldesktop`) || Path(`/s4ldesktopacad`) || Path(`/tis`) || Path(`/tiplite`) || Path(`/transpiled`) || Path(`/resource`) || PathPrefix(`/osparc/`) || PathPrefix(`/s4l/`) || PathPrefix(`/s4llite/`) || PathPrefix(`/s4lacad/`) || PathPrefix(`/s4lengine/`) || PathPrefix(`/s4ldesktop/`) || PathPrefix(`/s4ldesktopacad/`) || PathPrefix(`/tis/`) || PathPrefix(`/tiplite/`) || PathPrefix(`/transpiled/`) || PathPrefix(`/resource/`))
1499+ - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver_fallback.service=${SWARM_STACK_NAME}_static_webserver_fallback
1500+ - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver_fallback.entrypoints=http
1501+ - traefik.http.routers.${SWARM_STACK_NAME}_static_webserver_fallback.priority=1
1502+ # always fail and return 503 via unhealthy loadbalancer healthcheck
1503+ - traefik.http.services.${SWARM_STACK_NAME}_static_webserver_fallback.loadbalancer.server.port=0
1504+ - traefik.http.services.${SWARM_STACK_NAME}_static_webserver_fallback.loadbalancer.healthcheck.path=/some/invalid/path/to/generate/a/503
1505+ - traefik.http.services.${SWARM_STACK_NAME}_static_webserver_fallback.loadbalancer.healthcheck.interval=10s
1506+ - traefik.http.services.${SWARM_STACK_NAME}_static_webserver_fallback.loadbalancer.healthcheck.timeout=1ms
1507+
14551508volumes :
14561509 postgres_data :
14571510 name : ${SWARM_STACK_NAME}_postgres_data
0 commit comments