Docker images / prepare-release (push) Successful in 12s
Docker images / backend-test (push) Successful in 4m9s
Docker images / frontend-image (push) Successful in 4m28s
Docker images / updater-image (push) Successful in 58s
Docker images / backend-image (push) Successful in 2m49s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 11s
При старте backend накатывает схему PostgreSQL 18 и, если база пустая, один раз импортирует mikrotik.db с тома. Повторный старт не копирует данные. Бэкап в UI идёт через pg_dump. Co-authored-by: Cursor <cursoragent@cursor.com>
189 lines
5.5 KiB
YAML
189 lines
5.5 KiB
YAML
# MikrotikManager behind an existing CDNManager Traefik (no second Traefik).
|
|
#
|
|
# Prerequisite: CDNManager stack is up — network `cdnmanager` and container
|
|
# `cdnmanager-traefik` already publish :80/:443 and watch Docker labels.
|
|
#
|
|
# On server:
|
|
# mkdir -p /opt/mmapp/data /opt/mmapp/state /opt/mmapp/updater
|
|
# cp deploy/docker-compose.traefik-cdn.yml /opt/mmapp/docker-compose.yml
|
|
# cp deploy/env.traefik.example /opt/mmapp/.env
|
|
# # set MM_DOMAIN / CORS_ORIGIN; CF_* / LETSENCRYPT_* not required here
|
|
# cp deploy/updater/targets.json.example /opt/mmapp/updater/targets.json
|
|
# docker login git.shx.one
|
|
# cd /opt/mmapp && docker compose pull && docker compose up -d
|
|
#
|
|
# Equivalent plain CLI: deploy/run-beside-cdn-traefik.sh
|
|
#
|
|
# Traffic:
|
|
# Internet → CDNManager Traefik (:80/:443) → mmapp-frontend:3000 (network cdnmanager)
|
|
# └─ rewrite /api,/health → backend:8000 (network mmapp)
|
|
|
|
services:
|
|
postgres:
|
|
image: ${POSTGRES_IMAGE_TAG:-postgres:18-alpine}
|
|
container_name: mmapp-postgres
|
|
restart: unless-stopped
|
|
shm_size: "256mb"
|
|
environment:
|
|
POSTGRES_USER: mmapp
|
|
POSTGRES_DB: mmapp
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
|
|
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C.UTF-8 --data-checksums"
|
|
TZ: UTC
|
|
PGTZ: UTC
|
|
command:
|
|
- postgres
|
|
- -c
|
|
- timezone=UTC
|
|
- -c
|
|
- listen_addresses=*
|
|
- -c
|
|
- max_connections=100
|
|
- -c
|
|
- shared_buffers=256MB
|
|
- -c
|
|
- work_mem=16MB
|
|
- -c
|
|
- maintenance_work_mem=128MB
|
|
- -c
|
|
- wal_compression=on
|
|
volumes:
|
|
- mmapp-pgdata:/var/lib/postgresql/data
|
|
networks:
|
|
- mmapp
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U mmapp -d mmapp"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
backend:
|
|
image: git.shx.one/denozord/mikrotikmanager-backend:${MM_BACKEND_IMAGE_TAG:-latest}
|
|
pull_policy: always
|
|
container_name: mmapp-backend
|
|
restart: unless-stopped
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
environment:
|
|
NODE_ENV: production
|
|
PORT: "8000"
|
|
DATABASE_URL: postgres://mmapp:${POSTGRES_PASSWORD}@postgres:5432/mmapp
|
|
DATABASE_PATH: /app/data/mikrotik.db
|
|
CORS_ORIGIN: ${CORS_ORIGIN:-https://mm.shnt.top}
|
|
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
|
|
AUTH_JWT_SECRET: ${AUTH_JWT_SECRET:?set AUTH_JWT_SECRET in .env}
|
|
AUTH_ISSUER: ${AUTH_ISSUER:-https://auth.shnt.top}
|
|
AUTH_PORTAL_URL: ${AUTH_PORTAL_URL:-https://auth.shnt.top}
|
|
volumes:
|
|
- ./data:/app/data
|
|
networks:
|
|
mmapp:
|
|
aliases:
|
|
- backend
|
|
labels:
|
|
mmapp.updater.managed: "true"
|
|
mmapp.updater.target: backend
|
|
mmapp.updater.image: git.shx.one/denozord/mikrotikmanager-backend:${MM_BACKEND_IMAGE_TAG:-latest}
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"node",
|
|
"-e",
|
|
"fetch('http://127.0.0.1:8000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
|
]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 300s
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
frontend:
|
|
image: git.shx.one/denozord/mikrotikmanager-frontend:${MM_FRONTEND_IMAGE_TAG:-latest}
|
|
pull_policy: always
|
|
container_name: mmapp-frontend
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- backend
|
|
environment:
|
|
BACKEND_INTERNAL_URL: http://backend:8000
|
|
networks:
|
|
mmapp:
|
|
aliases:
|
|
- frontend
|
|
cdnmanager: {}
|
|
labels:
|
|
- mmapp.updater.managed=true
|
|
- mmapp.updater.target=frontend
|
|
- mmapp.updater.image=git.shx.one/denozord/mikrotikmanager-frontend:${MM_FRONTEND_IMAGE_TAG:-latest}
|
|
- traefik.enable=true
|
|
- traefik.docker.network=cdnmanager
|
|
- traefik.http.routers.mmapp.rule=Host(`${MM_DOMAIN:-mm.shnt.top}`)
|
|
- traefik.http.routers.mmapp.entrypoints=websecure
|
|
- traefik.http.routers.mmapp.tls=true
|
|
- traefik.http.routers.mmapp.tls.certresolver=letsencrypt
|
|
- traefik.http.services.mmapp.loadbalancer.server.port=3000
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"node",
|
|
"-e",
|
|
"fetch('http://127.0.0.1:3000/dashboard').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
|
]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 25s
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
updater:
|
|
image: git.shx.one/denozord/mikrotikmanager-updater:${MM_UPDATER_IMAGE_TAG:-latest}
|
|
pull_policy: always
|
|
container_name: mmapp-updater
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- frontend
|
|
environment:
|
|
REGISTRY: git.shx.one
|
|
REGISTRY_USERNAME: ${REGISTRY_USERNAME:-}
|
|
REGISTRY_PASSWORD: ${REGISTRY_PASSWORD:-}
|
|
POLL_INTERVAL_SECONDS: ${POLL_INTERVAL_SECONDS:-300}
|
|
HEALTH_TIMEOUT_SECONDS: ${HEALTH_TIMEOUT_SECONDS:-600}
|
|
STOP_TIMEOUT_SECONDS: ${STOP_TIMEOUT_SECONDS:-30}
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- ./state:/state
|
|
- ./updater/targets.json:/etc/updater/targets.json:ro
|
|
networks:
|
|
- mmapp
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
networks:
|
|
mmapp:
|
|
name: mmapp
|
|
cdnmanager:
|
|
external: true
|
|
name: cdnmanager
|
|
|
|
volumes:
|
|
mmapp-pgdata:
|