124 lines
4.0 KiB
YAML
124 lines
4.0 KiB
YAML
# Production deploy.
|
|
# API 51300 → Kestrel 8080
|
|
# SPA 5250 → nginx (кабинет + proxy /api и /u на tile-server)
|
|
# PG 5433 → Postgres (учётки, токены, стили, usage)
|
|
#
|
|
# docker compose up -d --build
|
|
#
|
|
# Persistent data (PBF, MBTiles, Planetiler sources, styles, keys) lives in the
|
|
# named volume `tile-server-data`. Image rebuilds and `docker compose up` do not
|
|
# touch it. Do NOT use `docker compose down -v` — that deletes the volume.
|
|
#
|
|
# If you already have files in ./data on the server, copy them once:
|
|
# docker run --rm -v "$(pwd)/data:/from:ro" -v tile-server-data:/to alpine \
|
|
# sh -c "cp -a /from/. /to/"
|
|
#
|
|
# Heap must stay well below mem_limit: Planetiler maps temp files outside -Xmx.
|
|
# Exit 137 = cgroup OOM killer. 8g heap in a 12g box dies on NW FO z15.
|
|
# After raising MaxZoom (z14→z15) the next startup rebuilds MBTiles; keep the volume.
|
|
|
|
services:
|
|
db:
|
|
image: postgres:16-alpine
|
|
container_name: tile-server-db
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_DB: ${POSTGRES_DB:-tile_server}
|
|
POSTGRES_USER: ${POSTGRES_USER:-tiles}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-tiles}
|
|
ports:
|
|
- "5433:5432"
|
|
volumes:
|
|
- tile-server-pg:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-tiles} -d ${POSTGRES_DB:-tile_server}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
|
|
tile-server:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
image: tile-server:latest
|
|
container_name: tile-server
|
|
restart: unless-stopped
|
|
init: true
|
|
env_file:
|
|
- path: .env
|
|
required: false
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
ports:
|
|
- "51300:8080"
|
|
environment:
|
|
ASPNETCORE_ENVIRONMENT: Production
|
|
ASPNETCORE_URLS: http://+:8080
|
|
TZ: UTC
|
|
TileServer__DataDirectory: /data
|
|
TileServer__JavaPath: /opt/java/openjdk/bin/java
|
|
TileServer__JvmMaxHeap: 4g
|
|
TileServer__PlanetilerThreads: "8"
|
|
TileServer__PlanetilerMmapTemp: "false"
|
|
TileServer__Sync__RunOnStartup: "true"
|
|
TileServer__Sync__Cron: "0 3 * * *"
|
|
TileServer__Sync__TimeZone: UTC
|
|
# Public origin for MapLibre (must be absolute https, not a relative path).
|
|
TileServer__PublicBaseUrl: https://tile-server.ru
|
|
# Yandex ID — same flat names as please_pay_me_bot. Secret only in .env.
|
|
YANDEX_CLIENT_ID: ${YANDEX_CLIENT_ID:-c76f28f3d66c447e85940a9a1f227452}
|
|
YANDEX_CLIENT_SECRET: ${YANDEX_CLIENT_SECRET:-}
|
|
YANDEX_REDIRECT_URI: ${YANDEX_REDIRECT_URI:-https://tile-server.ru}
|
|
TileServer__Yandex__ClientId: ${YANDEX_CLIENT_ID:-c76f28f3d66c447e85940a9a1f227452}
|
|
TileServer__Yandex__ClientSecret: ${YANDEX_CLIENT_SECRET:-}
|
|
TileServer__Yandex__RedirectUri: ${YANDEX_REDIRECT_URI:-https://tile-server.ru}
|
|
ConnectionStrings__Accounts: >-
|
|
Host=db;Port=5432;Database=${POSTGRES_DB:-tile_server};Username=${POSTGRES_USER:-tiles};Password=${POSTGRES_PASSWORD:-tiles}
|
|
volumes:
|
|
- tile-server-data:/data
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health/live"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 45s
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "5"
|
|
stop_grace_period: 2m
|
|
mem_limit: 12g
|
|
memswap_limit: 12g
|
|
|
|
tile-web:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
target: frontend
|
|
image: tile-server-web:latest
|
|
container_name: tile-server-web
|
|
restart: unless-stopped
|
|
depends_on:
|
|
tile-server:
|
|
condition: service_healthy
|
|
ports:
|
|
- "5250:80"
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1/"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 5
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
volumes:
|
|
tile-server-data:
|
|
name: tile-server-data
|
|
tile-server-pg:
|
|
name: tile-server-pg
|