x-db-environment: &db-environment POSTGRES_DB: mtl POSTGRES_USER: mtluser POSTGRES_PASSWORD: ${MTL_POSTGRES_PASSWORD:-MtlSuper123} x-image-pull-policy: &image-pull-policy ${MTL_IMAGE_PULL_POLICY:-always} services: db: image: postgis/postgis:18-3.6 environment: <<: *db-environment restart: unless-stopped memswap_limit: 512m volumes: - ./data/postgis:/var/lib/postgresql/18/docker healthcheck: test: ["CMD", "pg_isready", "-h", "127.0.0.1", "-U", "mtluser", "-d", "mtl"] interval: 1s timeout: 5s start_period: 5s retries: 60 deploy: resources: limits: memory: 512m # 384 MiB validated floor; 20% is 460.8 MiB, rounded to 512 MiB. reservations: memory: 256m command: > postgres -c shared_buffers=64MB -c effective_cache_size=160MB -c work_mem=1MB -c jit=off -c maintenance_work_mem=16MB -c max_connections=20 -c max_wal_size=1GB -c checkpoint_completion_target=0.9 -c wal_buffers=2MB -c synchronous_commit=off app: # Uses the published image unless MTL_APP_IMAGE is set in .env. # Developers testing a local build: # MTL_APP_IMAGE=mytraillog:local MTL_IMAGE_PULL_POLICY=never docker compose up -d image: ${MTL_APP_IMAGE:-wauwau0977/mytraillog:latest} pull_policy: *image-pull-policy depends_on: db: condition: service_healthy brouter: condition: service_started location-search: condition: service_started environment: <<: *db-environment SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/mtl SPRING_DATASOURCE_USERNAME: mtluser SPRING_DATASOURCE_PASSWORD: ${MTL_POSTGRES_PASSWORD:-MtlSuper123} MTL_DB_READONLY_PASSWORD: ${MTL_DB_READONLY_PASSWORD:-} MTL_USER_LOGIN: ${MTL_USER_LOGIN:-mtl} MTL_USER_PASSWORD: ${MTL_USER_PASSWORD:-change-me} MTL_UPDATES_ENABLED: ${MTL_UPDATES_ENABLED:-true} MTL_UPDATES_CHANNEL: ${MTL_UPDATES_CHANNEL:-stable} MTL_UPDATES_FEEDURL: ${MTL_UPDATES_FEED_URL:-https://mtl-explorer.com/releases/releases.json} MTL_UPDATES_COMPONENTS_BROUTER_MANAGEMENT: ${MTL_UPDATES_BROUTER_MANAGEMENT:-SELF_MANAGED} MTL_UPDATES_COMPONENTS_LOCATIONSEARCH_MANAGEMENT: ${MTL_UPDATES_LOCATION_SEARCH_MANAGEMENT:-SELF_MANAGED} # Set MTL_UPDATES_MAP_SERVER_MANAGEMENT=SELF_MANAGED in .env when you use offline maps (local-maps profile). MTL_UPDATES_COMPONENTS_MAPSERVER_MANAGEMENT: ${MTL_UPDATES_MAP_SERVER_MANAGEMENT:-PROVIDER_MANAGED} MTL_GPX_WATCH_DIRECTORY: /app/mtl-data/gpx MTL_GARMIN_SYNC_FIT_EXPORT_SAVE_DIR: /app/mtl-data/gpx MTL_GOOGLE_HEALTH_ENABLED: ${MTL_GOOGLE_HEALTH_ENABLED:-true} MTL_GOOGLE_HEALTH_CLIENT_ID: ${MTL_GOOGLE_HEALTH_CLIENT_ID:-} MTL_GOOGLE_HEALTH_CLIENT_SECRET: ${MTL_GOOGLE_HEALTH_CLIENT_SECRET:-} MTL_GOOGLE_HEALTH_REDIRECT_URI: ${MTL_GOOGLE_HEALTH_REDIRECT_URI:-} MTL_GOOGLE_HEALTH_STAGING_DIRECTORY: /app/mtl-data/google-health-staging MTL_PLANNER_ENABLED: "true" MTL_PLANNER_BROUTER_BASE_URL: http://brouter:17777 MTL_PLANNER_BROUTER_TIMEOUT_MS: "310000" MTL_PLANNER_STATUS_URL: http://brouter:17778/status MTL_LOCATION_SEARCH_STATUS_URL: http://location-search:8083/status MTL_LOCATION_SEARCH_QUERY_URL: http://location-search:8083/search SERVER_SSL_ENABLED: "false" ports: - "18080:8080" restart: unless-stopped stop_grace_period: 150s memswap_limit: 1248m volumes: # All your data lives in ./data. Keep gpx/ and google-health-staging/ # together in this folder; Google Health imports need them in one place. - ./data:/app/mtl-data # The app may only read these folders. - ./data/postgis:/app/mtl-data/postgis:ro - ./data/media:/app/mtl-data/media:ro - ./data/maps:/app/mtl-data/maps:ro - ./data/brouter-segments:/app/mtl-data/brouter-segments:ro - ./data/db-size-snapshots:/app/mtl-data/db-size-snapshots:ro - ./data/media:/app/media:ro - ./data/logs:/app/logs # Optional: your own server settings (for example Garmin sync): # - ./application.yml:/app/config/application.yml:ro deploy: resources: limits: memory: 1248m # Gives G1 a 500 MiB Java heap with the image's 40% heap limit. reservations: memory: 512m map-server: # Optional offline maps. Off by default; turn on with: # docker compose --profile local-maps up -d # Without it, maps load from the internet. profiles: ["local-maps"] # Override with MTL_MAP_IMAGE=mytraillog-maps:local and MTL_IMAGE_PULL_POLICY=never when testing a local build. image: ${MTL_MAP_IMAGE:-wauwau0977/mytraillog-maps:latest} pull_policy: *image-pull-policy ports: - "18081:8081" environment: PORT: "8081" LOWZOOM_MAXZOOM: "6" MAP_DOWNLOAD_URL: latest restart: unless-stopped memswap_limit: 128m volumes: - ./data/maps:/data deploy: resources: limits: memory: 128m # 96 MiB validated floor; 20% is 115.2 MiB, rounded to 128 MiB. reservations: memory: 64m location-search: image: ${MTL_LOCATION_SEARCH_IMAGE:-wauwau0977/mytraillog-location-search:latest} pull_policy: *image-pull-policy expose: - 8083 ports: - "18083:8083" environment: PORT: "8083" MTL_LOCATION_SEARCH_DB: /data/geonames-search.sqlite MTL_LOCATION_SEARCH_MMAP_SIZE: "33554432" restart: unless-stopped memswap_limit: 128m # Optional: use a place-search database you built yourself: # volumes: # - ./data/location-search/geonames-search.sqlite:/data/geonames-search.sqlite:ro deploy: resources: limits: memory: 128m # 96 MiB validated floor; 20% is 115.2 MiB, rounded to 128 MiB. reservations: memory: 64m brouter: # Override with MTL_BROUTER_IMAGE=mytraillog-brouter:local and MTL_IMAGE_PULL_POLICY=never when testing a local build. image: ${MTL_BROUTER_IMAGE:-wauwau0977/mytraillog-brouter:latest} pull_policy: *image-pull-policy expose: - 17777 - 17778 environment: BROUTER_JAVA_XMX: "128m" restart: unless-stopped memswap_limit: 512m volumes: - ./data/brouter-segments:/segments4 deploy: resources: limits: memory: 512m # 384 MiB validated floor; 20% is 460.8 MiB, rounded to 512 MiB. reservations: memory: 192m