services: parcel-tracker: build: . image: parcel-tracker-bot:local container_name: parcel-tracker-bot restart: unless-stopped env_file: .env ports: # Web dashboard (WEB_ENABLED=true). Bound to the host's loopback only: # put a reverse proxy in front to reach it from elsewhere (docs/operations.md). - "127.0.0.1:8080:8080" volumes: # Named volume: Docker seeds it with the image's /app/data ownership # (botuser), so the non-root process can create the DB on first run. # A ./data bind mount is created root-owned by the engine and breaks # first startup. - parcel-tracker-data:/app/data - ./plugins:/app/plugins:ro read_only: true tmpfs: - /tmp:size=64m,mode=1777 security_opt: - no-new-privileges:true cap_drop: - ALL mem_limit: 512m cpus: 1.0 pids_limit: 100 healthcheck: test: ["CMD", "python", "-c", "import os, pathlib, sqlite3; sqlite3.connect(pathlib.Path(os.getenv('DATABASE_PATH','/app/data/bot.db')).absolute().as_uri() + '?mode=ro', uri=True).execute('SELECT 1')"] interval: 5m timeout: 15s retries: 3 start_period: 30s logging: driver: json-file options: max-size: "10m" max-file: "5" volumes: parcel-tracker-data: