@@ -186,6 +186,7 @@ services:
186186 # internal traefik
187187 - traefik.enable =true
188188 - io.simcore.zone =${TRAEFIK_SIMCORE_ZONE}
189+ # NOTE: keep in sync with fallback router (rule and entrypoint)
189190 - traefik.http.routers.${SWARM_STACK_NAME}_invitations.rule =(${DEPLOYMENT_FQDNS_CAPTURE_INVITATIONS})
190191 - traefik.http.routers.${SWARM_STACK_NAME}_invitations.entrypoints =http
191192 - traefik.http.services.${SWARM_STACK_NAME}_invitations.loadbalancer.server.port =8000
@@ -769,9 +770,11 @@ services:
769770 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http.tls =true
770771 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http.middlewares =ops_gzip@swarm, ops_sslheader@swarm, ops_ratelimit@swarm
771772 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http.service =${SWARM_STACK_NAME}_simcore_http
773+ # Note: keep in sync with fallback router (rule and entrypoint)
772774 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http.rule =((${DEPLOYMENT_FQDNS_CAPTURE_TRAEFIK_RULE_CATCHALL}) && PathPrefix(` /`)) || ( (PathPrefix(` /dashboard`) || PathPrefix(` /api`) || PathPrefix(` /doc`) ) && Host(`traefikdashboard.${MACHINE_FQDN}`))
773775 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http.priority =3
774776 # oSparc publicAPI
777+ # Note: keep in sync with fallback router (rule and entrypoint)
775778 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api.rule =(${DEPLOYMENT_API_DOMAIN_CAPTURE_TRAEFIK_RULE}) && PathPrefix(` /`)
776779 - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api.entrypoints =https
777780 - traefik.http.services.${SWARM_STACK_NAME}_simcore_api.loadbalancer.server.port =10081
@@ -813,31 +816,96 @@ services:
813816 memory: 128M
814817 cpus: ' 0.1'
815818
816- traefik_api:
817- # NOTE: this is a trick to allow to access the internal traefik REST API
818- # A comment
819- # list router like so: curl https: //domain /api /http /routers | jq
819+ # use to define fallback routes for simcore traefik
820+ # if docker healthcheck fails, simcore traefik configurarion is
821+ # removed from ops traeifik https: //github.com /traefik /traefik /issues /7842
822+ #
823+ # use fallback routes to return proper 503 (instead of 404)
824+ # this service must be running at all times
825+ ops-traefik-configuration-placeholder: # TODO reuse same skeleton
820826 image: busybox:1.35.0
821- command: sleep 900000d
827+ command: sleep infinity
828+ networks:
829+ - public
830+ deploy:
831+ placement:
832+ constraints:
833+ - node.labels.traefik ==true
834+ resources:
835+ limits:
836+ memory: 16M
837+ cpus: ' 0.1'
838+ reservations:
839+ memory: 8M
840+ cpus: ' 0.1'
841+
842+ labels:
843+ # external traefik
844+ - traefik.enable =true
845+
846+ ### oSparc web (fallback low priority rule)
847+ # TODO: remove copy / paste
848+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http_fallback.entrypoints =https
849+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http_fallback.tls =true
850+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http_fallback.middlewares =ops_gzip@swarm, ops_sslheader@swarm, ops_ratelimit@swarm
851+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http_fallback.service =${SWARM_STACK_NAME}_simcore_http_fallback
852+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http_fallback.rule =((${DEPLOYMENT_FQDNS_CAPTURE_TRAEFIK_RULE_CATCHALL}) && PathPrefix(` /`)) || ( (PathPrefix(` /dashboard`) || PathPrefix(` /api`) || PathPrefix(` /doc`) ) && Host(`traefikdashboard.${MACHINE_FQDN}`))
853+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_http_fallback.priority =1
854+ # always return 503
855+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_http_fallback.loadbalancer.server.port =0
856+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_http_fallback.loadbalancer.healthcheck.path =/some/invalid/path/to/generate/a/503
857+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_http_fallback.loadbalancer.healthcheck.interval =10s
858+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_http_fallback.loadbalancer.healthcheck.timeout =1ms
859+
860+ ### oSparc publicAPI (fallback low priority rule)
861+ # TODO: remove copy / paste
862+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api_fallback.rule =(${DEPLOYMENT_API_DOMAIN_CAPTURE_TRAEFIK_RULE}) && PathPrefix(` /`)
863+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api_fallback.priority =1
864+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api_fallback.entrypoints =https
865+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api_fallback.tls =true
866+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api_fallback.middlewares =ops_gzip@swarm, ops_ratelimit@swarm
867+ - traefik.http.routers.${SWARM_STACK_NAME}_simcore_api_fallback.service =${SWARM_STACK_NAME}_simcore_api_fallback
868+ # always return 503
869+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_api_fallback.loadbalancer.server.port =0
870+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_api_fallback.loadbalancer.healthcheck.path =/some/invalid/path/to/generate/a/503
871+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_api_fallback.loadbalancer.healthcheck.interval =10s
872+ - traefik.http.services.${SWARM_STACK_NAME}_simcore_api_fallback.loadbalancer.healthcheck.timeout =1ms
873+
874+ traefik-configuration-placeholder: # simcore traefik with `io.simcore.zone =${TRAEFIK_SIMCORE_ZONE} ` label
875+ image: busybox:1.35.0
876+ command: sleep infinity
822877 networks:
823878 - default
824879 deploy:
825880 labels:
826881 # route to internal traefik
882+ - traefik.enable =true
827883 - io.simcore.zone =${TRAEFIK_SIMCORE_ZONE}
884+
828885 # traefik UI
829- - traefik.enable =true
830886 - traefik.http.routers.${SWARM_STACK_NAME}_traefik_api.service =api@internal
831887 - traefik.http.routers.${SWARM_STACK_NAME}_traefik_api.rule =(PathPrefix( ` /dashboard`) || PathPrefix(` /api`) ) && Host(`traefikdashboard.${MACHINE_FQDN}`)
832888 - traefik.http.routers.${SWARM_STACK_NAME}_traefik_api.entrypoints =http
833- - traefik.http.routers.${SWARM_STACK_NAME}_traefik_api.priority =6
834889 - traefik.http.routers.${SWARM_STACK_NAME}_traefik_api.middlewares =${SWARM_STACK_NAME}_auth@swarm, ${SWARM_STACK_NAME}_whitelist_ips@swarm
835890 - traefik.http.services.${SWARM_STACK_NAME}_traefik_api.loadbalancer.server.port =8080
891+
836892 # Middlewares
837893 # basic authentication
838894 - traefik.http.middlewares.${SWARM_STACK_NAME}_auth.basicauth.users =${TRAEFIK_USER}:${TRAEFIK_PASSWORD}
839895 # OPS IP Whitelist
840896 - traefik.http.middlewares.${SWARM_STACK_NAME}_whitelist_ips.ipallowlist.sourcerange =${TRAEFIK_IPWHITELIST_SOURCERANGE}
897+
898+ ### Fallback for invitations
899+ - traefik.http.routers.${SWARM_STACK_NAME}_invitations_fallback.rule =${DEPLOYMENT_FQDNS_CAPTURE_INVITATIONS}
900+ - traefik.http.routers.${SWARM_STACK_NAME}_invitations_fallback.service =${SWARM_STACK_NAME}_invitations_fallback
901+ - traefik.http.routers.${SWARM_STACK_NAME}_invitations_fallback.entrypoints =http
902+ - traefik.http.routers.${SWARM_STACK_NAME}_invitations_fallback.priority =1
903+ # always fail and return 503 via unhealthy loadbalancer healthcheck
904+ - traefik.http.services.${SWARM_STACK_NAME}_invitations_fallback.loadbalancer.server.port =0
905+ - traefik.http.services.${SWARM_STACK_NAME}_invitations_fallback.loadbalancer.healthcheck.path =/some/invalid/path/to/generate/a/503
906+ - traefik.http.services.${SWARM_STACK_NAME}_invitations_fallback.loadbalancer.healthcheck.interval =10s
907+ - traefik.http.services.${SWARM_STACK_NAME}_invitations_fallback.loadbalancer.healthcheck.timeout =1ms
908+
841909 update_config:
842910 parallelism: 2
843911 order: start-first
@@ -992,78 +1060,6 @@ services:
9921060 cpus: " 0.5"
9931061 memory: " 512M"
9941062
995- fallback-service-web:
996- image: nginx:1.25.1
997- configs:
998- - source: {{ SWARM_STACK_NAME }}_web_html
999- target: /usr /share /nginx /html /503.html
1000- - source: {{ SWARM_STACK_NAME }}_web_nginx_config
1001- target: /etc /nginx /conf.d /default.conf
1002- networks:
1003- - public
1004- - monitored
1005- deploy:
1006- placement:
1007- constraints:
1008- - node.labels.simcore ==true
1009- update_config:
1010- order: start-first
1011- labels:
1012- - io.simcore.zone =${TRAEFIK_SIMCORE_ZONE}
1013- - traefik.enable =true
1014-
1015- # webserver
1016- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_html.priority =1
1017- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_html.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/`))
1018- - traefik.http.services.${PREFIX_STACK_NAME}_fallback_html.loadbalancer.server.port=80
1019- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_html.entrypoints=http
1020-
1021- fallback-service-api:
1022- image: nginx:1.25.1
1023- configs:
1024- - source: {{ SWARM_STACK_NAME }}_api_json
1025- target: /usr/share/nginx/api/503.json
1026- - source: {{ SWARM_STACK_NAME }}_api_nginx_config
1027- target: /etc/nginx/conf.d/default.conf
1028- networks:
1029- - public
1030- - monitored
1031- deploy:
1032- placement:
1033- constraints:
1034- - node.labels.simcore==true
1035- update_config:
1036- order: start-first
1037- labels:
1038- - io.simcore.zone=${TRAEFIK_SIMCORE_ZONE}
1039- - traefik.enable=true
1040- # api-server
1041- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_api.priority=1
1042- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_api.rule=Path(`/`) || Path(`/v0`) || PathPrefix(`/v0/`) || Path(`/api/v0/openapi.json`)
1043- - traefik.http.services.${PREFIX_STACK_NAME}_fallback_api.loadbalancer.server.port=80
1044- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_api.entrypoints=simcore_api
1045- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_api.service=${PREFIX_STACK_NAME}_fallback_api
1046- # invitations
1047- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_invitations_api.priority=1
1048- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_invitations_api.rule=(${DEPLOYMENT_FQDNS_CAPTURE_INVITATIONS})
1049- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_invitations_api.entrypoints=http
1050- - traefik.http.services.${PREFIX_STACK_NAME}_fallback_invitations_api.loadbalancer.server.port=80
1051- - traefik.http.routers.${PREFIX_STACK_NAME}_fallback_invitations_api.service=${PREFIX_STACK_NAME}_fallback_invitations_api
1052-
1053- configs:
1054- {{ SWARM_STACK_NAME }}_web_html:
1055- file: ./configs/fallback-service-nginx/web/503.html
1056- name: {{ SWARM_STACK_NAME }}_web_html_{{ "./configs/fallback-service-nginx/web/503.html" | sha256file | substring(0,10) }}
1057- {{ SWARM_STACK_NAME }}_api_json:
1058- file: ./configs/fallback-service-nginx/api/503.json
1059- name: {{ SWARM_STACK_NAME }}_api_json_{{ "./configs/fallback-service-nginx/api/503.json" | sha256file | substring(0,10) }}
1060- {{ SWARM_STACK_NAME }}_web_nginx_config:
1061- file: ./configs/fallback-service-nginx/web/default.conf
1062- name: {{ SWARM_STACK_NAME }}_web_nginx_config_{{ "./configs/fallback-service-nginx/web/default.conf" | sha256file | substring(0,10) }}
1063- {{ SWARM_STACK_NAME }}_api_nginx_config:
1064- file: ./configs/fallback-service-nginx/api/default.conf
1065- name: {{ SWARM_STACK_NAME }}_api_nginx_config_{{ "./configs/fallback-service-nginx/api/default.conf" | sha256file | substring(0,10) }}
1066-
10671063volumes:
10681064 rabbit_data:
10691065 name: ${SWARM_STACK_NAME}_rabbit_data
0 commit comments