Multi deployment on docker Swarm
In this example, 3 stacks are deployed:
-
a traefik stack used as an http reverse proxy,
-
the elements of the keycloak stack are here in a dedicated stack,
-
the datachain stack, which will act as a client for the other two stacks.
All services are exposed via traefik. To facilitate deployment, each application has a dedicated domain, rather than working with uri. This avoids the risk of services sharing a URI. For example, here we have: traefik.demo.local, keycloak.demo.local, dc.demo.local for datachain, and spark.demo.local for the spark web GUI.
Traefik stack
This stack contains, with comments, the traefik configuration for requesting a certificate from let’s encrypt, to ensure https exchanges.
version: "3.7"
services:
traefik:
image: "traefik:${PRODUCT_VERSION}"
command:
- "--log.level=info"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.swarmMode=true"
- "--providers.docker.network=traefik_network"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
## Configuration in secure mode (https, whtih letsencrypt PKI (in this cas, URL must be public))
# - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
# - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
# - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
# - "--entrypoints.websecure.address=:443"
# - "--certificatesresolvers.resolver1.acme.httpchallenge=true"
# - "--certificatesresolvers.resolver1.acme.httpchallenge.entrypoint=web"
# - "--certificatesresolvers.resolver1.acme.email=postmaster@mysociety.acme.com"
# - "--certificatesresolvers.resolver1.acme.storage=/letsencrypt/dc_certs.json"
ports:
- "80:80"
## Configuration in secure mode
# - "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
## Configuration in secure mode
## Volume where letsencrypt certificates will be stored
# - "traefik_certs:/letsencrypt"
deploy:
mode: global
placement:
constraints:
# Always on manager for traefik
- node.role == manager
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
labels:
## CONFIGURATION DU DASHBOARD TRAEFIK
## Enable Dashboard visibility on traefik
- "traefik.enable=true"
- "traefik.docker.network=traefik_network"
## Dashboard config
- "traefik.http.routers.dashboard.entrypoints=web"
## Configuration in secure mode : comment previous line and uncomment the three
# - "traefik.http.routers.dashboard.tls=true"
# - "traefik.http.routers.dashboard.tls.certresolver=resolver1"
# - "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.rule=Host(`${TRAEFIK_URL}`)"
- "traefik.http.routers.dashboard.service=dashboard"
- "traefik.http.services.dashboard.loadbalancer.server.port=8080"
## Basic authentication, generated with command :
## echo $(htpasswd -nb admin password) | sed -e s/\\$/\\$\\$/g
## To authent, use admin as login and password as password
- "traefik.http.routers.dashboard.middlewares=traefik-auth@docker"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$mdAMA4f6$$2cfjZ7nxHcd.ABttomKqk1"
networks:
- traefik_network
## Configuration in secure mode : uncomment uncomment following lines
#volumes:
# traefik_certs:
networks:
## traefik_network is external : it must have been created before starting the stack
traefik_network:
external: true
Stack Keycloak
Note: traefik configuration, for application exposure.
version: "3.7"
services:
dc_pg_keycloak:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/pg_keycloak:${PRODUCT_VERSION}
networks:
kc_network:
aliases:
- dc-pg-keycloak
deploy:
mode: replicated
replicas: 1
volumes:
- keycloack_db:/var/lib/postgresql/data
dc_keycloak:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/keycloak:${PRODUCT_VERSION}
networks:
traefik_network:
kc_network:
aliases:
- dc-keycloak
env_file: keycloak.env
deploy:
mode: replicated
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_network"
- "traefik.http.routers.kc1_web_ui.rule=Host(`${KC_HOST}`) && PathPrefix(`/auth`)"
- "traefik.http.routers.kc1_web_ui.entrypoints=web"
## Configuration in secure mode : comment previous line and uncomment the three
# - "traefik.http.routers.kc1_web_ui.tls=true"
# - "traefik.http.routers.kc1_web_ui.tls.certresolver=resolver1"
# - "traefik.http.routers.kc1_web_ui.entrypoints=websecure"
- "traefik.http.services.kc1_web_ui.loadbalancer.server.port=8080"
## Enable compression
- "traefik.http.routers.kc1_web_ui.middlewares=kc1_web_comp1@docker"
- "traefik.http.middlewares.kc1_web_comp1.compress=true"
volumes:
keycloack_db:
networks:
## traefik_network is external : it must have been created before starting the stack
## kc_network is external : it must have been created before starting the stack
kc_network:
external: true
traefik_network:
external: true
DATACHAIN_CLIENT_URL=${DC_URL_PUBLIC}
KEYCLOAK_FRONTEND_URL=${KC_URL_PUBLIC}/auth
Stack Datachain
Note: traefik configuration, for application exposure.
version: "3.7"
services:
dc_redis_cache:
image: redis:7.0-alpine
command: redis-server --loglevel warning
networks:
dc_network:
aliases:
- dc-redis
deploy:
mode: replicated
replicas: 1
dc_pg:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/pg:${PRODUCT_VERSION}
networks:
dc_network:
aliases:
- dc-pg
command: ["postgres", "-c", "log_min_duration_statement=2000"]
deploy:
mode: replicated
replicas: 1
volumes:
- pg_data:/var/lib/postgresql/data
dc_pg_migration:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/pg_migration:${PRODUCT_VERSION}
networks:
dc_network:
aliases:
- dc-pg-migration
kc_network:
deploy:
restart_policy:
condition: none
volumes:
- pg_dump:/data/pg_dump
dc_pg_expose:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/pg_expose:${PRODUCT_VERSION}
networks:
dc_network:
aliases:
- dc-pg-expose
deploy:
mode: replicated
replicas: 1
volumes:
- pg_expose:/var/lib/postgresql/data
dc_backend:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/backend:${PRODUCT_VERSION}
networks:
traefik_network:
dc_network:
aliases:
- dc-backend
env_file: backend.env
deploy:
mode: replicated
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_network"
- "traefik.http.routers.dc_backend_actuator.rule=Host(`${DC_HOST}`) && PathPrefix(`/actuator`)"
- "traefik.http.routers.dc_backend_actuator.entrypoints=web"
## Configuration in secure mode : comment previous line and uncomment the three
# - "traefik.http.routers.dc_backend_actuator.tls=true"
# - "traefik.http.routers.dc_backend_actuator.tls.certresolver=resolver1"
# - "traefik.http.routers.dc_backend_actuator.entrypoints=websecure"
- "traefik.http.routers.dc_backend_actuator.service=dc_backend_actuator"
- "traefik.http.services.dc_backend_actuator.loadbalancer.server.port=9090"
## Basic authentication, generated with command :
## echo $(htpasswd -nb admin password) | sed -e s/\\$/\\$\\$/g
## To authent, use admin as login and password as password
- "traefik.http.routers.dc_backend_actuator.middlewares=dc_backend_actuator-auth@docker"
- "traefik.http.middlewares.dc_backend_actuator-auth.basicauth.users=admin:$$apr1$$mdAMA4f6$$2cfjZ7nxHcd.ABttomKqk1"
- "traefik.http.middlewares.dc_backend_actuator-auth.basicauth.removeheader=true"
dc_web_ui:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/web_ui:${PRODUCT_VERSION}
networks:
traefik_network:
dc_network:
aliases:
- dc-web-ui
env_file: web_ui.env
deploy:
mode: replicated
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_network"
- "traefik.http.routers.dc_web_ui.rule=Host(`${DC_HOST}`) && PathPrefix(`/`)"
- "traefik.http.routers.dc_web_ui.entrypoints=web"
## Configuration in secure mode : comment previous line and uncomment the three
# - "traefik.http.routers.dc_web_ui.entrypoints=websecure"
# - "traefik.http.routers.dc_web_ui.tls=true"
# - "traefik.http.routers.dc_web_ui.tls.certresolver=resolver1"
- "traefik.http.routers.dc_web_ui.service=dc_web_ui"
- "traefik.http.services.dc_web_ui.loadbalancer.server.port=80"
## Enable compression
- "traefik.http.routers.dc_web_ui1.middlewares=dc_web_comp1@docker"
- "traefik.http.middlewares.dc_web_comp1.compress=true"
dc_spark:
image: ${HARBOR_REGISTRY}/${HARBOR_PROJECT}/spark:${PRODUCT_VERSION}
networks:
traefik_network:
dc_network:
aliases:
- dc-spark1
env_file: spark.env
deploy:
mode: replicated
replicas: 1
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_network"
- "traefik.http.routers.dc_spark11.rule=Host(`${SPARK_HOST}`) && PathPrefix(`/actuator`)"
- "traefik.http.routers.dc_spark11.entrypoints=web"
## Configuration in secure mode : comment previous line and uncomment the three
# - "traefik.http.routers.dc_spark11.entrypoints=websecure"
# - "traefik.http.routers.dc_spark11.tls=true"
# - "traefik.http.routers.dc_spark11.tls.certresolver=resolver1"
- "traefik.http.routers.dc_spark11.service=dc_spark11"
- "traefik.http.services.dc_spark11.loadbalancer.server.port=9091"
## Basic authentication, generated with command :
## echo $(htpasswd -nb admin password) | sed -e s/\\$/\\$\\$/g
## To authent, use admin as login and password as password
- "traefik.http.routers.dc_spark11.middlewares=dc_spark11-auth@docker"
- "traefik.http.middlewares.dc_spark11-auth.basicauth.users=admin:$$apr1$$mdAMA4f6$$2cfjZ7nxHcd.ABttomKqk1"
- "traefik.http.middlewares.dc_spark11-auth.basicauth.removeheader=true"
## Expose spark UI :
- "traefik.http.routers.dc_spark11_web_ui.rule=Host(`${SPARK_HOST}`)"
- "traefik.http.routers.dc_spark11_web_ui.entrypoints=web"
## Configuration in secure mode : comment previous line and uncomment the three
# - "traefik.http.routers.dc_spark11_web_ui.entrypoints=websecure"
# - "traefik.http.routers.dc_spark11_web_ui.tls=true"
# - "traefik.http.routers.dc_spark11_web_ui.tls.certresolver=resolver1"
- "traefik.http.routers.dc_spark11_web_ui.service=dc_spark11_web_ui"
- "traefik.http.services.dc_spark11_web_ui.loadbalancer.server.port=4040"
volumes:
- hdfs:/data
healthcheck:
test: ["CMD", "curl", "-u", "backend:70171933-e656-4183-9955-bfd0354d2250", "-f", "http://localhost:9091/actuator/health"]
interval: 1m30s
timeout: 10s
retries: 6
start_period: 40s
volumes:
pg_data:
pg_dump:
hdfs:
pg_expose:
networks:
dc_network:
external: true
traefik_network:
external: true
kc_network:
external: true
# URL public avec http ou https
dc.app.url.web-ui=${DC_URL_PUBLIC}
# Configuration Keycloak
keycloak.auth-server-url=http://dc-keycloak:8080/auth
# Configuration base de donnée
dc.app.db.host=dc-pg
# Configuration du datasource d'exposition de donnée
spring.expose-datasource.host=dc-pg-expose
# Configuration Redis
dc.app.notification.urls=redis://dc-redis:6379
# Monitoring
management.server.address=0.0.0.0
## * to see all exposed url by actuator and call /actuator
# management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.include=health,metrics,prometheus,info
management.metrics.export.prometheus.enabled=true
# Configuration du contexte Spark
dc.app.context.url=http://dc-spark1:8090
# Configuration spark
dc.app.spark.master=local[6]
dc.app.spark.cores.max=6
dc.app.spark.executor.memory=8g
# Configuration HDFS
dc.app.data-file.hdfs=file:///data
# Configuration notifications
dc.app.notification.urls=redis://dc-redis:6379
# Monitoring
management.server.address=0.0.0.0
## * to see all exposed url by actuator and call /actuator
# management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.include=health,metrics,prometheus,info
management.metrics.export.prometheus.enabled=true
KEYCLOAK_CONFIG={"url": "${KC_URL_PUBLIC}/auth","realm": "dc-realm","clientId": "dc_front", "backendClientId": "dc_backend", "userRole" : "dc_user", "projectRole" : "dc_project", "adminRole" : "dc_admin", "memberRole" : "dc_member"}