Skip to content

Docker

Narratorr uses three key directories, typically mapped as Docker volumes:

Container PathPurposeBack Up?
/configDatabase, settings, configuration filesYes
/audiobooksYour audiobook libraryOptional (media can be re-downloaded)
/downloadsShared with download client for importNo
volumes:
- ./config:/config # Persist between container recreations
- /data/audiobooks:/audiobooks
- /data/downloads:/downloads

When Narratorr and your download client are in the same docker-compose.yml, use the service name as the hostname:

services:
narratorr:
image: narratorr/narratorr:latest
environment:
- PUID=1000 # default: 911
- PGID=1000 # default: 911
- TZ=America/New_York
# ...
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
# ...

In Narratorr’s download client settings, set host to qbittorrent (the service name), not localhost.

If a service runs on the host machine (not in Docker):

  • Linux: host.docker.internal doesn’t resolve by default — add extra_hosts: ["host.docker.internal:host-gateway"] to the narratorr service (Docker 20.10+) to enable it, or use the host’s LAN IP
  • Windows/macOS: Use host.docker.internal (built-in)

If services are in separate compose files, create a shared network:

# In both docker-compose files:
networks:
shared:
external: true
services:
narratorr:
networks:
- shared

Create the network first: docker network create shared

Narratorr exposes a health check endpoint:

GET /api/health

Returns 200 OK when the server is up and its database responds; if the database probe fails, it returns 503 even though the process is still running. Use this for container orchestration, monitoring, or load balancer health probes.

The image already defines its own HEALTHCHECK (with a built-in start period), so no manual configuration is needed. If you do want to override it — for example in a load balancer or external monitor — match what the image does so it keeps working under a reverse-proxy subpath:

services:
narratorr:
image: narratorr/narratorr:latest
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:3000${URL_BASE:-}/api/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
  1. Pull the latest image:

    Terminal window
    docker compose pull
  2. Recreate the container:

    Terminal window
    docker compose up -d

Your data persists in the mounted volumes. Database migrations run automatically on startup.

Back up the /config directory. It contains:

  • narratorr.db — your database (books, settings, indexer configs, download history)
  • Any other configuration files
Terminal window
# Simple backup
cp -r ./config ./config-backup-$(date +%Y%m%d)
# Or with a Docker volume
docker run --rm -v narratorr_config:/config -v $(pwd):/backup alpine \
tar czf /backup/narratorr-config-$(date +%Y%m%d).tar.gz /config

See Environment Variables for the complete reference. The Docker image sets production defaults automatically.

Because the image is based on LinuxServer.io, it also honors these standard variables:

  • PUID / PGID — the runtime UID/GID used for file ownership of everything Narratorr writes (config database, imported audiobooks). Default 911; set them to match the owner of your host directories. See the volume-permissions note under Common Issues.
  • TZ — the container timezone (e.g. America/New_York), used for log timestamps and scheduling.
  • Container can’t write to volumes — Narratorr runs as the unprivileged abc user (LinuxServer.io base image). Set PUID/PGID to match the UID/GID that owns your host directories (default 911). Run id on the host to find the right values.
  • Can’t connect to download client — use service names, not localhost. See Troubleshooting.
  • Downloads complete but don’t import — the /downloads volume must be accessible to both containers with matching paths. See Remote Path Mappings.