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