▍Все контейнеры в docker-compose для Docker Swarm¶
Необходимые требования¶
У вас должны быть:
Подготовительный этап¶
Создадим структуру директорий:
Дерево каталогов:
┌─( daffin@srv-manager ) - ( 30 files, 112K ) - ( / )
└─> tree -d -L 1 /docker
/docker
├── backup
├── build
├── conf
├── data
├── logs
└── swarm
Docker-compose¶
Устанавливаем вторую версию Docker compose
$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
$ docker-compose -v
Docker Compose version v2.15.1
Docker Stack¶
Ниже приведены стеки с перечнем сервисов:
┌─( root@swarm-manager1 ) - ( 23 files, ) - ( /docker/swarm )
└─> ls
total 90K
drw------- 2 root root 18 мар 5 14:19 ./
drwxr-xr-x 9 root root 9 янв 19 10:20 ../
-rw------- 1 root root 4,4K мар 4 12:53 archive.yml
-rw------- 1 root root 1019 мар 4 12:54 backups.yml
-rw------- 1 root root 3,3K мар 4 12:55 cloud.yml
-rw------- 1 root root 1,7K мар 4 12:55 control.yml
-rw------- 1 root root 2,7K янв 28 12:30 dashboard.yml
-rw------- 1 root root 11K мар 4 12:56 database.yml
-rw------- 1 root root 4,1K мар 4 11:50 dev.yml
-rw------- 1 root root 2,2K мар 4 12:57 gpt.yml
-rw------- 1 root root 5,5K мар 4 15:00 immich.yml
-rw------- 1 root root 12K мар 4 15:01 monitoring.yml
-rw------- 1 root root 3,6K мар 4 12:50 registry.yml
-rw------- 1 root root 16K мар 4 15:07 service.yml
-rw------- 1 root root 1010 янв 16 11:59 update.yml
-rw------- 1 root root 6,0K мар 4 15:09 www.yml
-rw------- 1 root root 3,5K мар 5 13:58 zcrontab.yml
Для их запуска используем команду:
Для массового запуска можно создать, например, такой скрипт:
#!/bin/bash
DIR="/docker/swarm"
cd $DIR
case "$1" in
on)
find . -name "*.yml" ! -name 'docker-compose.yml' -print0 | while read -d $'\0' staks
do
stakname=$(basename -- "$staks")
docker stack deploy --with-registry-auth -c "${stakname%.*}".yml "${stakname%.*}"
done
;;
off)
find . -name "*.yml" ! -name 'docker-compose.yml' -print0 | while read -d $'\0' staks
do
stakname=$(basename -- "$staks")
docker stack rm "${stakname%.*}"
done
;;
*)
echo "Usage: $0 (on|off)"
;;
esac
Для запуска всех сервисов:
Чтобы погасить всё:
Т.к. все контейнеры у меня загружены в локальный Docker Registry, то используется ключ "--with-registry-auth" для авторизации. Данные авторизации лежат в домашней директории пользователя, для root
это /root/.docker/config.json
. Этот файл появится после выполнения шага авторизации в регистри docker login https://registry.example.com
. Далее этот файл нужно скопировать на все сервера нашего кластера.
Stack www.yml¶
version: '3.9'
services:
traefik:
image: traefik:latest
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
- target: 443
published: 443
protocol: udp
mode: host
depends_on:
- authelia
environment:
- [email protected]
- CF_DNS_API_TOKEN=11111111222222222333333344444445555555
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /docker/conf/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- /docker/conf/traefik/data:/data
networks:
- traefik-public
deploy:
replicas: 2
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
placement:
constraints: [node.role == manager]
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.ru`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=traefik:$$apr1$$3BL6MNLt$$TYlUAcgfkmwRGD9JTVlA11" # traefik PaSSw0rd для генерации используй: echo $(htpasswd -nb user PaSSw0rd) | sed -e s/\\$/\\$\\$/g
- "traefik.http.middlewares.WhitelistHome.ipwhitelist.sourcerange=172.18.0.0/24, 172.19.0.0/24, 172.20.0.0/24, 192.168.0.0/16, 10.0.0.0/8"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.example.ru`)"
- "traefik.http.services.traefik-secure.loadbalancer.server.port=8080"
- "traefik.http.routers.traefik-secure.middlewares=WhitelistHome,traefik-auth,CORS@file"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=example.ru"
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.example.ru"
- "traefik.http.routers.traefik-secure.service=api@internal"
- "prometheus-job=traefik"
- "prometheus-port=8181"
authelia:
image: registry.example.ru/authelia:latest
environment:
- TZ=Europe/Moscow
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
placement:
constraints: [node.role == manager]
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.authelia.rule=Host(`login.example.ru`)'
- 'traefik.http.routers.authelia.entrypoints=https'
- 'traefik.http.routers.authelia.tls=true'
- 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://login.example.ru/'
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true'
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email'
- 'traefik.http.middlewares.authelia-basic.forwardauth.address=http://authelia:9091/api/verify?auth=basic'
- 'traefik.http.middlewares.authelia-basic.forwardauth.trustForwardHeader=true'
- 'traefik.http.middlewares.authelia-basic.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email'
- "traefik.http.services.authelia.loadbalancer.server.port=9091"
- "traefik.docker.network=traefik-public"
volumes:
traefik:
networks:
traefik-public:
external: true
Stack registry.yml¶
version: "3.9"
services:
registry:
image: registry:latest
volumes:
- /docker/data/registry:/var/lib/registry
- /docker/conf/registry/auth:/auth
- /etc/localtime:/etc/localtime:ro
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_DELETE_ENABLED: 'true'
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.registry.rule=Host(`registry.example.ru`)"
- "traefik.http.routers.registry.entrypoints=https"
- "traefik.http.routers.registry.tls=true"
- "traefik.http.routers.registry.middlewares=WhitelistHome"
- "traefik.http.services.registry.loadbalancer.server.port=5000"
registry-ui:
image: registry.example.ru/docker-registry-ui:main
environment:
- SINGLE_REGISTRY=true
- REGISTRY_TITLE=Docker Registry UI
- DELETE_IMAGES=true
- SHOW_CONTENT_DIGEST=true
- NGINX_PROXY_PASS_URL=http://registry:5000
- SHOW_CATALOG_NB_TAGS=true
- CATALOG_MIN_BRANCHES=1
- CATALOG_MAX_BRANCHES=1
- TAGLIST_PAGE_SIZE=100
- REGISTRY_SECURED=false
- CATALOG_ELEMENTS_LIMIT=1000
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.registry-ui.rule=Host(`registry.example.ru`)"
- "traefik.http.routers.registry-ui.entrypoints=https"
- "traefik.http.routers.registry-ui.tls=true"
- "traefik.http.routers.registry-ui.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.registry-ui.loadbalancer.server.port=80"
# При удалении образов удаляются только ссылки, для физического удаления необходимо запустить сборщик мусора:
# docker exec -it registry_registry.1.uujkkcs9v6pyqthkaqcxrdzon registry garbage-collect /etc/docker/registry/config.yml
verdaccio:
image: registry.example.ru/verdaccio
environment:
- VERDACCIO_PORT=4873
volumes:
- /docker/data/verdaccio:/verdaccio/storage
- /docker/conf/verdaccio:/verdaccio/conf
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.verdaccio.rule=Host(`npm.example.ru`)"
- "traefik.http.routers.verdaccio.entrypoints=https"
- "traefik.http.routers.verdaccio.tls=true"
- "traefik.http.routers.verdaccio.middlewares=WhitelistHome"
- "traefik.http.services.verdaccio.loadbalancer.server.port=4873"
networks:
traefik-public:
external: true
Stack monitoring.yml¶
version: "3.9"
services:
grafana:
image: registry.example.ru/grafana-oss:latest
environment:
GF_REMOTE_CACHE_TYPE: redis
GF_REMOTE_CACHE_CONNSTR: addr=redis:6379,pool_size=100,db=0,ssl=false
volumes:
- /docker/data/grafana:/var/lib/grafana
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.routers.grafana.rule=Host(`grafana.example.ru`)"
- "traefik.http.routers.grafana.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
elasticsearch:
image: registry.example.ru/elasticsearch:8.4.3
hostname: 'elasticsearch'
environment:
- discovery.type=single-node
- ELASTIC_PASSWORD=paSSw0rd
- xpack.license.self_generated.type=basic
- path.data=/usr/share/elasticsearch/data
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- /docker/data/elasticsearch:/usr/share/elasticsearch/data
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
kibana:
image: registry.example.ru/kibana:latest #8.4.3
depends_on:
- elasticsearch
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- KIBANA_URL=http://kibana.example.ru
- SERVER_NAME=kibana
- PATH_DATA=/usr/share/kibana/data
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=paSSw0rd
volumes:
- /docker/data/kibana:/usr/share/kibana/data
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.kibana.tls=true"
- "traefik.http.routers.kibana.rule=Host(`kibana.example.ru`)"
- "traefik.http.routers.kibana.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.kibana.loadbalancer.server.port=5601"
prometheus:
image: registry.example.ru/prometheus:latest
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention=750h' # автоочистка данных старше месяца
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
depends_on:
- cadvisor
volumes:
- /docker/data/prometheus:/prometheus
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == manager]
labels:
- "traefik.enable=true"
- "traefik.http.routers.prometheus.rule=Host(`prometheus.example.ru`)"
- "traefik.http.routers.prometheus.entrypoints=https"
- "traefik.http.routers.prometheus.tls=true"
- "traefik.http.routers.prometheus.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
node-exporter:
image: registry.example.ru/node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/host:ro,rslave
command:
- '--path.rootfs=/host'
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- --collector.filesystem.mount-points-exclude
- "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)"
networks:
- traefik-public
deploy:
mode: global
resources:
limits:
memory: 128M
reservations:
memory: 64M
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
labels:
- prometheus-job=node-exporter
- prometheus-port=9100
fluentd:
image: registry.example.ru/fluentd:latest
ports:
- 5140:5140/udp
environment:
- FLUENTD_PASSWORD=paSSw0rd
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
cadvisor:
image: registry.example.ru/cadvisor
command:
- --docker_only
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
networks:
- traefik-public
deploy:
mode: global
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
labels:
- "prometheus-job=cadvisor"
- "prometheus-port=8080"
mysql-zabbix:
image: registry.example.ru/mariadb:10.8
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/mysql-zabbix:/var/lib/mysql:Z
environment:
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_zabbix
- MYSQL_PASSWORD_FILE=/run/secrets/mysql_zabbix
- MYSQL_USER=zabbix
- MYSQL_DATABASE=zabbix
secrets:
- mysql_root_zabbix
- mysql_zabbix
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
zabbix-web-nginx-mysql:
image: registry.example.ru/zabbix-web-nginx-mysql:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
environment:
DB_SERVER_HOST: mysql-zabbix
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD_FILE: /run/secrets/mysql_zabbix
secrets:
- mysql_zabbix
depends_on:
- mysql-zabbix
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.zabbix.tls=true"
- "traefik.http.routers.zabbix.rule=Host(`zabbix.example.ru`)"
- "traefik.http.routers.zabbix.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.zabbix.loadbalancer.server.port=8080"
zabbix-java-gateway:
image: registry.example.ru/zabbix-java-gateway:latest
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
zabbix-server-mysql:
image: registry.example.ru/zabbix-server-mysql:latest
depends_on:
- zabbix-java-gateway
- mysql-zabbix
environment:
DB_SERVER_HOST: mysql-zabbix
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD_FILE: /run/secrets/mysql_zabbix
ZBX_JAVAGATEWAY: zabbix-java-gateway
secrets:
- mysql_zabbix
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
uptimekuma:
image: registry.example.ru/uptime-kuma:latest
volumes:
- /docker/conf/uptimekuma:/app/data
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.uptime.tls=true"
- "traefik.http.routers.uptime.rule=Host(`uptime.example.ru`)"
- "traefik.http.routers.uptime.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.uptime.loadbalancer.server.port=3001"
alertmanager:
image: registry.example.ru/alertmanager:latest
environment:
- SMTP_SERVER=smtp.mail.ru:465
- [email protected]
- [email protected]
- [email protected]
- SMTP_AUTH_PASSWORD_FILE=/run/secrets/smtp_passwd
secrets:
- smtp_passwd
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
placement:
constraints: [node.role == worker]
secrets:
mysql_root_zabbix:
external: true
mysql_zabbix:
external: true
smtp_passwd:
external: true
volumes:
mysql-zabbix:
networks:
traefik-public:
external: true
Stack control.yml¶
version: "3.9"
services:
portainer:
image: registry.example.ru/portainer-ce
command: -H tcp://tasks.agent:9001 --tlsskipverify
environment:
TZ: Europe/Moscow
volumes:
- /docker/conf/portainer:/data
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
placement:
constraints: [node.role == manager]
labels:
- "traefik.enable=true"
- "traefik.http.routers.portainer.rule=Host(`portainer.example.ru`)"
- "traefik.http.routers.portainer.entrypoints=https"
- "traefik.http.routers.portainer.tls=true"
- "traefik.http.routers.portainer.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
agent:
image: registry.example.ru/agent
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
environment:
AGENT_CLUSTER_ADDR: tasks.agent
networks:
- traefik-public
deploy:
mode: global
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
resources:
limits:
memory: 128M
reservations:
memory: 64M
networks:
traefik-public:
external: true
Stack database.yml¶
version: "3.9"
services:
postgres:
image: registry.example.ru/postgres:15.3
command:
- "postgres"
- "-c"
- "max_connections=500"
- "-c"
- "work_mem=16MB"
- "-c"
- "maintenance_work_mem=512MB"
- "-c"
- "log_min_duration_statement=200ms"
- "-c"
- "idle_in_transaction_session_timeout=10s"
- "-c"
- "lock_timeout=1s"
- "-c"
- "statement_timeout=60s"
- "-c"
- "shared_preload_libraries=pg_stat_statements"
- "-c"
- "pg_stat_statements.max=10000"
- "-c"
- "pg_stat_statements.track=all"
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 30s
timeout: 20s
retries: 7
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/postgresql:/var/lib/postgresql/data:Z
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD_FILE=/run/secrets/postgresql_root
- POSTGRES_INITDB_ARGS=--data-checksums
- PGDATA=/var/lib/postgresql/data/swarm
secrets:
- postgresql_root
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
resources:
limits:
cpus: '2'
memory: 2048M
reservations:
cpus: '0.5'
memory: 512M
postgres-backup:
image: registry.example.ru/postgres:15.3
depends_on:
- postgres
environment:
- BACKUP_NUM_KEEP=30
- BACKUP_FREQUENCY=1d
- PASSWORD=/run/secrets/postgresql_root
secrets:
- postgresql_root
volumes:
- /docker/backup/postgres_dump:/dump
- /etc/localtime:/etc/localtime:ro
entrypoint: |
bash -c 'bash -s <<EOF
trap "break;exit" SIGHUP SIGINT SIGTERM
sleep 2m
export PGPASSWORD=`cat $$PASSWORD`
while /bin/true; do
pg_dumpall -U postgres -h postgres | gzip > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.sql.gz
ls -tr /dump/dump_*.gz | head -n -"$$BACKUP_NUM_KEEP" | xargs -r rm
sleep $$BACKUP_FREQUENCY
done
EOF'
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 120s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
mysql:
image: registry.example.ru/mariadb:10.8
environment:
- MARIADB_AUTO_UPGRADE=1
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/mysql_root
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-S", "/var/lib/mysql/mysqld.sock", "--silent"]
interval: 5s
timeout: 5s
retries: 10
secrets:
- mysql_root
volumes:
- /docker/conf/50-server.cnf:/etc/mysql/mariadb.conf.d/50-server.cnf
- /docker/backup/mysql_dump:/dump:ro
- /docker/data/init.db/init.sql:/docker-entrypoint-initdb.d/init.sql
- /docker/data/mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: on-failure
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
mysql-backup:
image: registry.example.ru/mariadb:10.8
depends_on:
- mysql
environment:
- BACKUP_NUM_KEEP=30
- BACKUP_FREQUENCY=1d
- ROOT=/run/secrets/mysql_root
secrets:
- mysql_root
volumes:
- /docker/backup/mysql_dump:/dump
- /etc/localtime:/etc/localtime:ro
entrypoint: |
bash -c 'bash -s <<EOF
trap "break;exit" SIGHUP SIGINT SIGTERM
sleep 2m
while /bin/true; do
mysqldump -h mysql -p`cat $$ROOT` --events --routines --triggers -A --opt | gzip -c > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.sql.gz
ls -tr /dump/dump_*.sql.gz | head -n -"$$BACKUP_NUM_KEEP" | xargs -r rm
sleep $$BACKUP_FREQUENCY
done
EOF'
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
redis:
image: registry.example.ru/redis:7.0-alpine
command: redis-server --appendonly yes --loglevel warning
healthcheck:
test: ["CMD", "redis-cli", "ping"]
volumes:
- /docker/data/redis:/data:Z
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
resources:
limits:
cpus: '0.25'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
minio:
image: registry.example.ru/minio:latest
command: server /data --address ":9000" --console-address ":9001"
environment:
MINIO_ROOT_USER: minio
MINIO_ROOT_PASSWORD_FILE: /run/secrets/minio_root
secrets:
- minio_root
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/minio:/data:Z
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.s3web.rule=Host(`s3web.example.ru`)"
- "traefik.http.routers.s3web.entrypoints=https"
- "traefik.http.routers.s3web.tls=true"
- "traefik.http.routers.s3web.middlewares=WhitelistHome"
- "traefik.http.services.s3web.loadbalancer.server.port=9001"
phpmyadmin:
image: registry.example.ru/phpmyadmin:latest
environment:
- PMA_ARBITRARY=0
- PMA_HOSTS=mysql
- UPLOAD_LIMIT=500M
- HIDE_PHP_VERSION=true
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.pma.tls=true"
- "traefik.http.routers.pma.rule=Host(`pma.example.ru`)"
- "traefik.http.routers.pma.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.pma.loadbalancer.server.port=80"
pgadmin:
image: registry.example.ru/pgadmin4:latest
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD_FILE: /run/secrets/pgadmin
PGADMIN_LISTEN_PORT: 80
secrets:
- pgadmin
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.pgadmin.tls=true"
- "traefik.http.routers.pgadmin.rule=Host(`pgadmin.example.ru`)"
- "traefik.http.routers.pgadmin.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.pgadmin.loadbalancer.server.port=80"
adminer:
image: registry.example.ru/adminer:latest
environment:
- ADMINER_PLUGINS=tinymce
- ADMINER_DESIGN=nette
- ADMINER_DEFAULT_SERVER=mysql
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.adminer.tls=true"
- "traefik.http.routers.adminer.rule=Host(`adminer.example.ru`)"
- "traefik.http.routers.adminer.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.adminer.loadbalancer.server.port=8080"
resources:
limits:
cpus: '0.25'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
secrets:
postgresql_root:
external: true
mysql_root:
external: true
mysql_root_synology:
external: true
pgadmin:
external: true
minio_root:
external: true
networks:
traefik-public:
external: true
Stack dev.yml¶
version: '3.9'
services:
### DEVELOPMENT
codeserver:
image: registry.example.ru/code-server:latest
command: --auth none --disable-telemetry
volumes:
- /docker/conf/codeserver/coder:/home/coder
- /docker/data/projects:/home/coder/projects
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.codeserver.tls=true"
- "traefik.http.routers.codeserver.rule=Host(`codeserver.example.ru`)"
- "traefik.http.routers.codeserver.middlewares=WhitelistHome,authelia@docker,CORS@file"
- "traefik.http.services.codeserver.loadbalancer.server.port=8080"
gitlab:
image: registry.example.ru/gitlab-ce:latest
environment:
# GITLAB_SKIP_UNMIGRATED_DATA_CHECK: 'true'
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://gitlab.example.ru'
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
"X-Forwarded-Proto" => "https",
"X-Forwarded-Ssl" => "on"
}
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.mail.ru"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "[email protected]"
gitlab_rails['smtp_password'] = "paSSw0rd"
gitlab_rails['smtp_domain'] = "mail.ru"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
gitlab_rails['gitlab_email_from'] = '[email protected]'
gitlab_rails['gitlab_email_reply_to'] = '[email protected]'
patroni['remove_data_directory_on_rewind_failure'] = true
patroni['remove_data_directory_on_diverged_timelines'] = true
ports:
- "2222:22"
volumes:
- /docker/conf/gitlab:/etc/gitlab
- /docker/data/gitlab:/var/opt/gitlab
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 600s
failure_action: continue
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitlab.tls=true"
- "traefik.http.routers.gitlab.rule=Host(`gitlab.example.ru`)"
- "traefik.http.routers.gitlab.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
gitlab-runner:
image: registry.example.ru/gitlab-runner:latest
volumes:
- /docker/conf/gitlab-runner:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
gitlab-runner-swarm:
image: registry.example.ru/gitlab-runner:latest
volumes:
- /docker/conf/gitlab-runner-swarm:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
networks:
traefik-public:
external: true
Stack cloud.yml¶
version: "3.9"
services:
nextcloud:
image: registry.example.ru/nextcloud:latest
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/www/nextcloud.example.ru:/var/www/html
- /docker/data/nextcloud:/data
- type: tmpfs
target: /tmp
healthcheck:
test: curl http://127.0.0.1:80/login || exit 1
start_period: 60s
interval: 60s
timeout: 30s
retries: 15
depends_on:
- postgres
- redis
environment:
REDIS_HOST: redis
POSTGRES_HOST: postgres
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_nextcloud
TRUSTED_PROXIES: 'traefik 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8'
NEXTCLOUD_TRUSTED_DOMAINS: nextcloud.example.ru
NEXTCLOUD_DATA_DIR: /data
secrets:
- postgres_nextcloud
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
resources:
limits:
cpus: '2'
memory: 768M
reservations:
cpus: '1'
memory: 512M
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.middlewares=nextcloud,nextcloud_redirect"
- "traefik.http.routers.nextcloud.tls=true"
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.example.ru`)"
- "traefik.http.routers.nextcloud.middlewares=default-headers@file,nextcloud_redirect,CORS@file"
- "traefik.http.middlewares.nextcloud.headers.customFrameOptionsValue=ALLOW-FROM https://nextcloud.example.ru"
- "traefik.http.middlewares.nextcloud.headers.contentSecurityPolicy=frame-ancestors 'self' nextcloud.example.ru *.example.ru"
- "traefik.http.middlewares.nextcloud_redirect.redirectregex.permanent=true"
- "traefik.http.middlewares.nextcloud_redirect.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav"
- "traefik.http.middlewares.nextcloud_redirect.redirectregex.replacement=https://$${1}/remote.php/dav/"
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
- "traefik.docker.network=traefik-public"
secrets:
postgres_nextcloud:
external: true
networks:
traefik-public:
external: true
Stack immich.yml¶
version: "3.9"
services:
server:
image: registry.example.ru/immich-server:release
command: [ "start.sh", "immich" ]
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/immich/upload:/usr/src/app/upload
depends_on:
- dbimmich
- redis
environment:
REDIS_HOSTNAME: redis
DB_HOSTNAME: dbimmich
DB_USERNAME: immich
DB_DATABASE_NAME: immich
DB_PASSWORD_FILE: /run/secrets/postgres_immich
NODE_ENV: production
JWT_SECRET: 1234567899098765432132423564767
LOG_LEVEL: error
PUBLIC_LOGIN_PAGE_MESSAGE: "My Family Photos and Videos Backup Server"
REVERSE_GEOCODING_PRECISION: 3
secrets:
- postgres_immich
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.immich.rule=Host(`immich.example.ru`)"
- "traefik.http.routers.immich.entrypoints=https"
- "traefik.http.routers.immich.tls=true"
- "traefik.http.routers.immich.middlewares=default-headers@file,CORS@file"
- "traefik.http.services.immich.loadbalancer.server.port=3001"
microservices:
image: registry.example.ru/immich-server:release
command: [ "start.sh", "microservices" ]
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/immich/upload:/usr/src/app/upload
depends_on:
- dbimmich
- redis
- server
environment:
REDIS_HOSTNAME: redis
DB_HOSTNAME: dbimmich
DB_USERNAME: immich
DB_DATABASE_NAME: immich
DB_PASSWORD_FILE: /run/secrets/postgres_immich
NODE_ENV: production
JWT_SECRET: 1234567899098765432132423564767
LOG_LEVEL: error
REVERSE_GEOCODING_PRECISION: 3
secrets:
- postgres_immich
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
machine-learning:
image: registry.example.ru/immich-machine-learning:release
volumes:
- /docker/data/immich/cache:/cache
environment:
REDIS_HOSTNAME: redis
DB_HOSTNAME: dbimmich
DB_USERNAME: immich
DB_DATABASE_NAME: immich
DB_PASSWORD_FILE: /run/secrets/postgres_immich
LOG_LEVEL: error
REVERSE_GEOCODING_PRECISION: 3
secrets:
- postgres_immich
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
postgres-backup-immich:
image: tensorchord/pgvecto-rs:pg16-v0.2.0
environment:
- BACKUP_NUM_KEEP=30
- BACKUP_FREQUENCY=1d
- PASSWORD=/run/secrets/postgres_immich
secrets:
- postgres_immich
volumes:
- /docker/backup/postgres_dump_immich:/dump
- /etc/localtime:/etc/localtime:ro
entrypoint: |
bash -c 'bash -s <<EOF
trap "break;exit" SIGHUP SIGINT SIGTERM
sleep 2m
export PGPASSWORD=`cat $$PASSWORD`
while /bin/true; do
pg_dumpall -U immich -h dbimmich | gzip > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.sql.gz
ls -tr /dump/dump_*.gz | head -n -"$$BACKUP_NUM_KEEP" | xargs -r rm
sleep $$BACKUP_FREQUENCY
done
EOF'
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: on-failure
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
dbimmich:
image: tensorchord/pgvecto-rs:pg16-v0.2.0
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/immich/postgresql:/var/lib/postgresql/data:Z
environment:
- POSTGRES_USER=immich
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_immich
- POSTGRES_DB=immich
- POSTGRES_INITDB_ARGS=--data-checksums
secrets:
- postgres_immich
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
resources:
limits:
cpus: '2'
memory: 2048M
reservations:
cpus: '0.5'
memory: 512M
secrets:
postgres_immich:
external: true
networks:
traefik-public:
external: true
Stack dashboard.yml¶
version: '3.9'
services:
homer:
image: registry.example.ru/homer:latest
volumes:
- /docker/conf/homer:/www/assets
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.homer.rule=Host(`homer.example.ru`)"
- "traefik.http.routers.homer.entrypoints=https"
- "traefik.http.routers.homer.tls=true"
- "traefik.http.routers.homer.middlewares=WhitelistHome"
- "traefik.http.services.homer.loadbalancer.server.port=8080"
heimdall:
image: registry.example.ru/heimdall:latest
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Moscow
volumes:
- /docker/conf/heimdall:/config
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.heimdall.rule=Host(`heimdall.example.ru`)"
- "traefik.http.routers.heimdall.entrypoints=https"
- "traefik.http.routers.heimdall.tls=true"
- "traefik.http.routers.heimdall.middlewares=WhitelistHome"
- "traefik.http.services.heimdall.loadbalancer.server.port=80"
homarr:
image: ghcr.io/ajnart/homarr:latest
volumes:
- /docker/conf/homarr/configs:/app/data/configs
- /docker/conf/homarr/icons:/app/public/icons
- /docker/conf/homarr/data:/data
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.homarr.rule=Host(`homarr.example.ru`)"
- "traefik.http.routers.homarr.entrypoints=https"
- "traefik.http.routers.homarr.tls=true"
- "traefik.http.routers.homarr.middlewares=WhitelistHome"
- "traefik.http.services.homarr.loadbalancer.server.port=7575"
networks:
traefik-public:
external: true
Stack service.yml¶
version: '3.9'
services:
trilium:
image: registry.example.ru/trilium:0.45-latest
environment:
- TRILIUM_DATA_DIR=/data
volumes:
- /docker/data/trilium:/data
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.trilium.rule=Host(`trilium.example.ru`)"
- "traefik.http.routers.trilium.entrypoints=https"
- "traefik.http.routers.trilium.tls=true"
- "traefik.http.routers.trilium.middlewares=authelia@docker,CORS@file"
- "traefik.http.services.trilium.loadbalancer.server.port=8080"
vault:
image: registry.example.ru/vault
command: vault server -config=/vault/config/vault.json
environment:
- VAULT_ADDR=http://0.0.0.0:8200
- VAULT_API_ADDR=http://0.0.0.0:8200
- VAULT_ADDRESS=http://0.0.0.0:8200
volumes:
- /docker/conf/vault:/vault
- /docker/conf/vault/file:/vault/file
cap_add:
- IPC_LOCK
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.vault.rule=Host(`vault.example.ru`)"
- "traefik.http.routers.vault.entrypoints=https"
- "traefik.http.routers.vault.tls=true"
- "traefik.http.routers.vault.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.vault.loadbalancer.server.port=8200"
vaultwarden:
image: registry.example.ru/server:latest
environment:
- WEBSOCKET_ENABLED=true # Enable WebSocket notifications.
- SIGNUPS_ALLOWED=false
volumes:
- /docker/conf/vaultwarden:/data
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.vaultwarden.tls=true"
- "traefik.http.routers.vaultwarden.middlewares=default-headers@file,CORS@file"
- "traefik.http.routers.vaultwarden.rule=Host(`vaultwarden.example.ru`)"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
ipam:
image: registry.example.ru/ipam:latest
volumes:
- /etc/localtime:/etc/localtime:ro
environment:
- MYSQL_ENV_MYSQL_DB=ipam
- MYSQL_ENV_MYSQL_USER=ipam
- MYSQL_ENV_MYSQL_PASSWORD=paSSw0rd
- MYSQL_ENV_MYSQL_HOST=mysql
depends_on:
- mysql
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.ipam.tls=true"
- "traefik.http.routers.ipam.rule=Host(`ipam.example.ru`)"
- "traefik.http.routers.ipam.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.ipam.loadbalancer.server.port=80"
ocs:
image: registry.example.ru/ocsinventory-docker-image:latest
volumes:
- /etc/localtime:/etc/localtime:ro
environment:
OCS_DB_SERVER: mysql
OCS_DB_USER: ocs
OCS_DB_PASS: paSSw0rd
OCS_DB_NAME: ocsweb
OCS_OPT_DBI_PRINT_ERROR: 1
depends_on:
- mysql
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.ocs.tls=true"
- "traefik.http.routers.ocs.rule=Host(`ocs.example.ru`)"
- "traefik.http.routers.ocs.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.ocs.loadbalancer.server.port=80"
syncthing:
image: registry.example.ru/syncthing:latest
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/conf/syncthing:/var/syncthing/config
- /docker/data/syncthing:/var/syncthing
ports:
- "22000:22000"
- "21027:21027/udp"
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.syncthing.rule=Host(`syncthing.example.ru`)"
- "traefik.http.routers.syncthing.entrypoints=https"
- "traefik.http.routers.syncthing.tls=true"
- "traefik.http.routers.syncthing.middlewares=WhitelistHome,authelia@docker,CORS@file"
- "traefik.http.services.syncthing.loadbalancer.server.port=8384"
altmirror:
image: registry.example.ru/altmirror:latest
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/alt-mirror:/alt-mirror
networks:
- traefik-public
ports:
- 8080:80
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == manager]
labels:
- "traefik.enable=true"
- "traefik.http.routers.altmirror.rule=Host(`altmirror.example.ru`)"
- "traefik.http.routers.altmirror.entrypoints=https"
- "traefik.http.routers.altmirror.tls=true"
- "traefik.http.routers.altmirror.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.altmirror.loadbalancer.server.port=80"
rutorrent:
image: registry.example.ru/rutorrent
environment:
- PUID=1000
- PGID=1000
ports:
- 51413:51413
- 6881:6881/udp
volumes:
- /docker/conf/rutorrent:/config
- /media/TORRENTS:/downloads
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: on-failure
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.rutorrent.rule=Host(`torrents.example.ru`)"
- "traefik.http.routers.rutorrent.entrypoints=https"
- "traefik.http.routers.rutorrent.tls=true"
- "traefik.http.routers.rutorrent.middlewares=WhitelistHome"
- "traefik.http.services.rutorrent.loadbalancer.server.port=80"
speedtest:
image: registry.example.ru/latest:latest
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.speedtest.rule=Host(`speedtest.example.ru`)"
- "traefik.http.routers.speedtest.entrypoints=https"
- "traefik.http.routers.speedtest.tls=true"
- "traefik.http.routers.speedtest.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.speedtest.loadbalancer.server.port=3000"
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
depends_on:
- gotenberg
- tika
healthcheck:
test: ["CMD", "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000"]
interval: 30s
timeout: 10s
retries: 5
environment:
- PAPERLESS_TIME_ZONE=Europe/Moscow
- PAPERLESS_ADMIN_USER=admin
- PAPERLESS_ADMIN_PASSWORD=paSSw0rd
- PAPERLESS_URL=https://paper.example.ru
- [email protected]
- PAPERLESS_REDIS=redis://redis:6379
- PAPERLESS_TIKA_ENABLED=1
- PAPERLESS_TIKA_GOTENBERG_ENDPOINT=http://gotenberg:3000
- PAPERLESS_TIKA_ENDPOINT=http://tika:9998
volumes:
- /docker/data/paperless/data:/usr/src/paperless/data
- /docker/data/paperless/media:/usr/src/paperless/media
- /docker/data/paperless/export:/usr/src/paperless/export
- /docker/data/paperless/consume:/usr/src/paperless/consume
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.paperless.rule=Host(`paper.example.ru`)"
- "traefik.http.routers.paperless.entrypoints=https"
- "traefik.http.routers.paperless.tls=true"
- "traefik.http.routers.paperless.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.paperless.loadbalancer.server.port=8000"
gotenberg:
image: thecodingmachine/gotenberg
environment:
- DISABLE_GOOGLE_CHROME=1
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
tika:
image: apache/tika
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
jellyfin:
image: registry.example.ru/jellyfin
volumes:
- /docker/conf/jellyfin/config:/config
- /media/ФИЛЬМЫ:/data/movies:ro
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Moscow
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: on-failure
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.example.ru`)"
- "traefik.http.routers.jellyfin.entrypoints=https"
- "traefik.http.routers.jellyfin.tls=true"
- "traefik.http.routers.jellyfin.middlewares=WhitelistHome,default-headers@file"
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
networks:
traefik-public:
external: true
Stack archive.yml¶
version: '3.9'
services:
### LOCAL ARCHIVE
archivebox:
image: registry.example.ru/archivebox
volumes:
- /docker/data/archivebox:/data
environment:
- ALLOWED_HOSTS=*
- MEDIA_MAX_SIZE=750m
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.archive.rule=Host(`archive.example.ru`)"
- "traefik.http.routers.archive.entrypoints=https"
- "traefik.http.routers.archive.tls=true"
- "traefik.http.routers.archive.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.archive.loadbalancer.server.port=8000"
ytdl_material:
image: registry.example.ru/youtubedl-material:latest
environment:
- ALLOW_CONFIG_MUTATIONS=true
- ytdl_use_local_db=true
- write_ytdl_config=true
volumes:
- /docker/conf/ytdl/appdata:/app/appdata
- /media/YOUTUBE:/app/video
- /docker/conf/ytdl/subscriptions:/app/subscriptions
- /docker/conf/ytdl/users:/app/users
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.ytdl.rule=Host(`youtube.example.ru`)"
- "traefik.http.routers.ytdl.entrypoints=https"
- "traefik.http.routers.ytdl.tls=true"
- "traefik.http.routers.ytdl.middlewares=WhitelistHome"
- "traefik.http.services.ytdl.loadbalancer.server.port=17442"
kiwix:
image: registry.example.ru/kiwix-serve:3.5.0
volumes:
- /docker/data/wikipedia:/data
command:
wikipedia_ru_all_maxi_2022-12.zim
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.kiwix.rule=Host(`wikipedia.example.ru`)"
- "traefik.http.routers.kiwix.entrypoints=https"
- "traefik.http.routers.kiwix.tls=true"
- "traefik.http.routers.kiwix.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.kiwix.loadbalancer.server.port=8080"
offline-map:
image: registry.example.ru/offline-map:latest
volumes:
- /docker/data/maps:/usr/share/nginx/html/map:ro
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.offline-map.rule=Host(`map.example.ru`)"
- "traefik.http.routers.offline-map.entrypoints=https"
- "traefik.http.routers.offline-map.tls=true"
- "traefik.http.routers.offline-map.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.offline-map.loadbalancer.server.port=80"
networks:
traefik-public:
external: true
Stack update.yml¶
version: "3.9"
services:
shepherd:
image: registry.example.ru/shepherd:latest
volumes:
- /root/.docker/config.json:/root/.docker/config.json:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
TZ: 'Europe/Moscow'
SLEEP_TIME: '5m'
IGNORELIST_SERVICES: 'shepherd control_portainer service_archivebox-cron dev_gitlab www_traefik www_npm'
FILTER_SERVICES: ''
VERBOSE: 'true'
IMAGE_AUTOCLEAN_LIMIT: '5'
WITH_REGISTRY_AUTH: 'true'
UPDATE_OPTIONS: '--update-delay=30s'
ROLLBACK_OPTIONS: '--rollback-delay=0s'
ROLLBACK_ON_FAILURE: 'true'
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == manager]
networks:
traefik-public:
external: true
Stack backups.yml¶
version: '3.9'
services:
duplicati:
image: registry.example.ru/duplicati:latest
environment:
- PUID=0
- PGID=0
- TZ=Europe/Moscow
volumes:
- /docker/conf/duplicati:/config
- /docker:/docker
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.duplicati.rule=Host(`duplicati.example.ru`)"
- "traefik.http.routers.duplicati.entrypoints=https"
- "traefik.http.routers.duplicati.tls=true"
- "traefik.http.services.duplicati.loadbalancer.server.port=8200"
- "traefik.http.routers.duplicati.middlewares=WhitelistHome,authelia@docker,CORS@file"
networks:
traefik-public:
external: true
Stack gpt.yml¶
version: '3.9'
services:
private-gpt:
image: registry.example.ru/privategpt:latest
environment:
- PORT=8080
- PGPT_PROFILES=docker
- PGPT_MODE=local
- PGPT_HF_REPO_ID=IlyaGusev/saiga_mistral_7b_gguf
- PGPT_HF_MODEL_FILE=model-q4_K.gguf
- PGPT_EMBEDDING_HF_MODEL_NAME=BAAI/bge-small-en-v1.5
volumes:
- /docker/data/private-gpt/local_data:/home/worker/app/local_data
- /docker/data/private-gpt/models:/home/worker/app/models
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.gpt.rule=Host(`gpt.example.ru`)"
- "traefik.http.routers.gpt.entrypoints=https"
- "traefik.http.routers.gpt.tls=true"
- "traefik.http.routers.gpt.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.gpt.loadbalancer.server.port=8080"
qdrant:
image: qdrant/qdrant:latest
volumes:
- /docker/data/qdrant:/qdrant/storage
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: stop-first
placement:
constraints: [node.role == worker]
labels:
- "traefik.enable=true"
- "traefik.http.routers.qdrant.rule=Host(`qdrant.example.ru`)"
- "traefik.http.routers.qdrant.entrypoints=https"
- "traefik.http.routers.qdrant.tls=true"
- "traefik.http.routers.qdrant.middlewares=WhitelistHome,CORS@file"
- "traefik.http.services.qdrant.loadbalancer.server.port=6333"
networks:
traefik-public:
external: true
Stack zcrontab.yml¶
version: '3.9'
services:
swarm-cronjob:
image: crazymax/swarm-cronjob:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- "TZ=Europe/Moscow"
- "LOG_LEVEL=info"
- "LOG_JSON=false"
networks:
- traefik-public
deploy:
replicas: 1
restart_policy:
condition: any
delay: 5s
window: 120s
update_config:
parallelism: 1
monitor: 60s
failure_action: rollback
order: start-first
placement:
constraints: [node.role == manager]
nextcloud-cron-job:
image: registry.example.ru/nextcloud:latest
networks:
- traefik-public
command: su www-data -s /usr/local/bin/php -f /var/www/html/cron.php
environment:
REDIS_HOST: redis
POSTGRES_HOST: postgres
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_nextcloud
secrets:
- postgres_nextcloud
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/www/nextcloud.example.ru:/var/www/html
- /docker/data/nextcloud:/data
- type: tmpfs
target: /tmp
deploy:
mode: replicated
replicas: 0
labels:
- "swarm.cronjob.enable=true"
- "swarm.cronjob.schedule=*/5 * * * *"
- "swarm.cronjob.skip-running=false"
restart_policy:
condition: none
nextcloud-cron2-job:
image: registry.example.ru/nextcloud:latest
networks:
- traefik-public
command: su www-data -s /data/cron.sh
environment:
REDIS_HOST: redis
POSTGRES_HOST: postgres
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_nextcloud
secrets:
- postgres_nextcloud
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/data/www/nextcloud.example.ru:/var/www/html
- /docker/data/nextcloud:/data
- type: tmpfs
target: /tmp
deploy:
mode: replicated
replicas: 0
labels:
- "swarm.cronjob.enable=true"
- "swarm.cronjob.schedule=0 4 * * *"
- "swarm.cronjob.skip-running=false"
restart_policy:
condition: none
gitlab-cron-backup-job:
image: registry.example.ru/gitlab-ce:latest
networks:
- traefik-public
command: su git -s /usr/bin/gitlab-backup create
volumes:
- /docker/conf/gitlab:/etc/gitlab
- /docker/data/gitlab:/var/opt/gitlab
- /etc/localtime:/etc/localtime:ro
deploy:
mode: replicated
replicas: 0
labels:
- "swarm.cronjob.enable=true"
- "swarm.cronjob.schedule=0 1 * * *"
- "swarm.cronjob.skip-running=false"
restart_policy:
condition: none
paperless-cron-backup-job:
image: paperlessngx/paperless-ngx
networks:
- traefik-public
command: document_exporter /usr/src/paperless/export --zip
volumes:
- /docker/data/paperless/data:/usr/src/paperless/data
- /docker/data/paperless/media:/usr/src/paperless/media
- /docker/data/paperless/export:/usr/src/paperless/export
- /docker/data/paperless/consume:/usr/src/paperless/consume
deploy:
mode: replicated
replicas: 0
labels:
- "swarm.cronjob.enable=true"
- "swarm.cronjob.schedule=0 1 * * *"
- "swarm.cronjob.skip-running=false"
restart_policy:
condition: none
secrets:
postgres_nextcloud:
external: true
networks:
traefik-public:
external: true
Создание секретов¶
echo "paSSw0rd" | docker secret create mysql_root -
echo "paSSw0rd" | docker secret create minio_root -
echo "paSSw0rd" | docker secret create mysql_root_zabbix -
echo "paSSw0rd" | docker secret create mysql_zabbix -
echo "paSSw0rd" | docker secret create fluentd -
echo "paSSw0rd" | docker secret create smtp_passwd -
echo "paSSw0rd" | docker secret create kibana_system_passwd -
echo "paSSw0rd" | docker secret create pgadmin -
echo "paSSw0rd" | docker secret create postgres_nextcloud -
echo "paSSw0rd" | docker secret create postgresql_root -
echo "paSSw0rd" | docker secret create postgres_immich -