Skip to content

Docker Compose Deployment

BirdNET-NG runs as a 7-container stack behind a Traefik reverse proxy.

Containers

ContainerImagePurpose
postgresPostgreSQL 17Multi-tenant data store
redisRedis 7BullMQ job queue backend
mosquittoMosquitto 2.xMQTT broker (dynamic security plugin)
minioMinIOS3-compatible audio + image storage
hubNode.jsAPI gateway, MQTT ingester, background workers
webnginxReact SPA, proxies /api/* to hub
workerPython 3.11BirdNET inference (scalable)

Networks

  • traefik (external) — Traefik routes HTTPS/MQTTS/WSS traffic
  • backend (internal) — Inter-container communication

Storage

All persistent data uses bind mounts under BNG_VOLUMES_ROOT (default: ./storage/):

storage/
├── postgres/    # Database files
├── redis/       # Redis AOF
├── mosquitto/   # Broker data + dynamic security DB
└── minio/       # Audio blobs + species images

Scaling Workers

bash
docker compose up --scale worker=4 -d

Workers are stateless — add as many as needed for your detection volume.

Commands

bash
# Start full stack
docker compose up -d

# Rebuild after code changes
docker compose up -d --build

# View logs
docker compose logs -f hub

# Run database migrations
docker compose exec hub node packages/hub/dist/db/migrate.js

# Stop everything
docker compose down

Traefik Configuration

Three entrypoints are needed:

EntrypointPortProtocolService
websecure443HTTPSWeb UI + API
mqtts8883TCP (TLS)MQTT broker
websecure443HTTPSMinIO console

The docker-compose.yml includes Traefik labels for automatic routing.

Distributed bird sound identification