Continuing the discussion from Docker Swarm + Portainer: Frappe only, need ERPNext:
@Ysedky, would you mind sharing how you were able to create multiple sites on docker swarm?
Here is what I did so far:
- Create two stacks one for traefik and another one for portainer, they both work well. Traefik was able to detect portainer as soon as I deploy the stack
- Create a stack for mariadb which also works well
- Create a stack for redis, nginx, frappe and erpnext. Traefik detected the site created from that stack successfully.
My problem is how to have traefik detect additional sites. I tried creating additional sites first by modifying and restarting the site creator service from the initial stack, the site was successfully created according to the container log, but I cannot access it because traefik did not detect it (I guess nginx neither). I was also able to create multiple additional sites by manually creating new containers using portainer, creation went well according to the logs⌠except traefik never detected those sites (only the first one created with the initial stack). I was thinking about duplicating the initial stack, but I guess I would end up filling the server with duplicate containers for all the different services.
My post is very long and Iâm sorry for that, but I felt like attaching the codes would help the community better understand my problem. Thank you for your help.
traefik-stack
version: â3.9â
services:
traefik:
depends_on:
- socket-traefik
image: traefik:v2.6.1
command:
- --providers.docker
- --providers.docker.endpoint=tcp://socket-proxy:2375
- --providers.docker.constraints=Label(traefik.constraint-label
, cloud-public
)
- --providers.docker.exposedByDefault=false
- --providers.docker.swarmMode=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.api.address=:8083
- --certificatesresolvers.letsencrypt.acme.email=${EMAIL?Variable not set}
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.letsencrypt.acme.tlschallenge=true
- --log=true
- --log.filePath=/logs/traefik.log
- --log.level=DEBUG
- --accesslog=true
- --accesslog.filepath=/logs/access.log
- --accesslog.bufferingsize=25
- --api
deploy:
restart_policy:
condition: on-failure
placement:
constraints:
- ânode.labels.traefik-node.traefik-certificates == trueâ
- ânode.role == managerâ
labels:
- âtraefik.enable=trueâ
- âtraefik.docker.network=traefik-intâ
- âtraefik.constraint-label=cloud-publicâ
- âtraefik.http.routers.http-redirects.entrypoints=webâ
- âtraefik.http.routers.http-redirects.rule=hostregexp({host:(www\.)?.+}
)â
- âtraefik.http.routers.http-redirects.middlewares=traefik-ratelimit,redirect-to-non-www-httpsâ
- âtraefik.http.routers.www-redirects.entrypoints=websecureâ
- âtraefik.http.routers.www-redirects.rule=hostregexp({host:(www\.).+}
)â
- âtraefik.http.routers.www-redirects.tls=trueâ
- âtraefik.http.routers.www-redirects.middlewares=traefik-ratelimit,redirect-to-non-www-httpsâ
- âtraefik.http.middlewares.redirect-to-non-www-https.redirectregex.regex=^https?://(?:www.)?(.+)â
- âtraefik.http.middlewares.redirect-to-non-www-https.redirectregex.replacement=https://$${1}â
- âtraefik.http.middlewares.redirect-to-non-www-https.redirectregex.permanent=trueâ
- âtraefik.http.routers.api.entrypoints=apiâ
- âtraefik.http.routers.api.rule=Host(traefik.${DOMAIN?Variable not set}
)â
- âtraefik.http.routers.api.service=api@internalâ
- âtraefik.http.routers.api.tls=trueâ
- âtraefik.http.routers.api.tls.certresolver=letsencryptâ
- âtraefik.http.routers.api.middlewares=api-ipwhitelist,traefik-ratelimit,api-authâ
- âtraefik.http.middlewares.api-auth.basicauth.users=${TRAEFIK_ADMINS?Variable not set}â
- âtraefik.http.middlewares.api-ipwhitelist.ipwhitelist.sourcerange=172.18.0.0/16, x.x.x.xâ
- âtraefik.http.services.api.loadbalancer.server.port=8083â
- âtraefik.http.routers.traefik-secure.tls.domains[0].main=${DOMAIN?Variable not set}â
- âtraefik.http.routers.traefik-secure.tls.domains[0].sans=*.${DOMAIN?Variable not set}â
- âtraefik.http.middlewares.traefik-ratelimit.ratelimit.average=100â
- âtraefik.http.middlewares.traefik-ratelimit.ratelimit.burst=50â
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
- target: 8083
published: 8083
protocol: tcp
mode: host
volumes:
- /opt/traefik-certificates:/letsencrypt
- /opt/traefik-logs:/logs
- /opt/traefik-config:/etc/traefik
networks:
- traefik-int
- socket-int
socket-traefik:
image: tecnativa/docker-socket-proxy:latest
deploy:
restart_policy:
condition: on-failure
placement:
constraints:
- ânode.role == managerâ
environment:
NETWORKS: 1
SERVICES: 1
TASKS: 1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket-int
networks:
traefik-int:
external: true
socket-int:
driver: overlay
driver_opts:
encrypted: âtrueâ
erpnext-stack
version: â3.7â
services:
redis-cache:
image: redis:latest
volumes:
- redis_cache_vol:/data
deploy:
restart_policy:
condition: on-failure
networks:
- erpnext-network
redis-queue:
image: redis:latest
volumes:
- redis_queue_vol:/data
deploy:
restart_policy:
condition: on-failure
networks:
- erpnext-network
redis-socketio:
image: redis:latest
volumes:
- redis_socketio_vol:/data
deploy:
restart_policy:
condition: on-failure
networks:
- erpnext-network
erpnext-nginx:
image: frappe/erpnext-nginx:${ERPNEXT_VERSION}
environment:
- FRAPPE_PY=frappe-python
- FRAPPE_PY_PORT=8000
- FRAPPE_SOCKETIO=frappe-socketio
- SOCKETIO_PORT=9000
networks:
- erpnext-network
- traefik-int
volumes:
- sites_vol:/var/www/html/sites:rw
- assets_vol:/assets:rw
deploy:
restart_policy:
condition: on-failure
labels:
- âtraefik.enable=trueâ
- âtraefik.docker.network=traefik-intâ
- âtraefik.constraint-label=cloud-publicâ
- âtraefik.http.routers.erpnext-nginx.entrypoints=websecureâ
- âtraefik.http.routers.erpnext-nginx.rule=Host(${SITES?Variable not set})â
- âtraefik.http.routers.erpnext-nginx-https.rule=Host(${SITES?Variable not set})â
- âtraefik.http.routers.erpnext-nginx-https.tls=trueâ
- âtraefik.http.routers.erpnext-nginx-https.tls.certresolver=letsencryptâ
- âtraefik.http.services.erpnext-nginx.loadbalancer.server.port=8080â
frappe-python:
image: frappe/erpnext-worker:${ERPNEXT_VERSION}
deploy:
restart_policy:
condition: on-failure
environment:
- MARIADB_HOST=${MARIADB_HOST}
- REDIS_CACHE=redis-cache:6379
- REDIS_QUEUE=redis-queue:6379
- REDIS_SOCKETIO=redis-socketio:6379
- SOCKETIO_PORT=9000
- AUTO_MIGRATE=1
networks:
- erpnext-network
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
- assets_vol:/home/frappe/frappe-bench/sites/assets:rw
frappe-socketio:
image: frappe/frappe-socketio:${FRAPPE_VERSION}
deploy:
restart_policy:
condition: on-failure
networks:
- erpnext-network
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
- logs_vol:/home/frappe/frappe-bench/logs:rw
erpnext-worker-default:
image: frappe/erpnext-worker:${ERPNEXT_VERSION}
deploy:
restart_policy:
condition: on-failure
command: worker
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
- logs_vol:/home/frappe/frappe-bench/logs:rw
networks:
- erpnext-network
erpnext-worker-short:
image: frappe/erpnext-worker:${ERPNEXT_VERSION}
deploy:
restart_policy:
condition: on-failure
command: worker
environment:
- WORKER_TYPE=short
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
- logs_vol:/home/frappe/frappe-bench/logs:rw
networks:
- erpnext-network
erpnext-worker-long:
image: frappe/erpnext-worker:${ERPNEXT_VERSION}
deploy:
restart_policy:
condition: on-failure
command: worker
environment:
- WORKER_TYPE=long
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
networks:
- erpnext-network
erpnext-schedule:
image: frappe/erpnext-worker:${ERPNEXT_VERSION}
deploy:
restart_policy:
condition: on-failure
command: schedule
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
- logs_vol:/home/frappe/frappe-bench/logs:rw
networks:
- erpnext-network
erpnext-site-creator:
image: frappe/erpnext-worker:${ERPNEXT_VERSION}
deploy:
restart_policy:
condition: none
command: new
depends_on:
- frappe-python
environment:
- SITE_NAME=${SITE_NAME}
- DB_ROOT_USER=${DB_ROOT_USER}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- INSTALL_APPS=${INSTALL_APPS}
networks:
- erpnext-network
volumes:
- sites_vol:/home/frappe/frappe-bench/sites:rw
- logs_vol:/home/frappe/frappe-bench/logs:rw
volumes:
redis_cache_vol:
redis_queue_vol:
redis_socketio_vol:
assets_vol:
sites_vol:
logs_vol:
networks:
erpnext-network:
external: true
traefik-int:
external: true