Solving Librespot Freezes and Discovery Issues with Avahi in Docker

Let me prefix this post with saying: I am not expert. I’m figuring this out as I go.


I was experiencing issues running Librespot inside a Docker container (on Ubuntu Server). When switching quickly between Spotify Connect devices–or even just disconnecting and directly connecting again, Librespot would often freeze and throw errors about unknown packages.

I found the root cause lay in the mDNS (multicast DNS) backend used for service advertising. Librespot’s default libmdns was not stable enough in Docker, especially when handling device switches.

To fix this, I switched the mDNS backend to use Avahi, a more mature and robust zeroconf/mDNS daemon running on the host, my homelab Muninn. Luckily, giof71/librespot:latest is build with backend switching enabled.

Oh yea. Don’t forget to install Avahi.

sudo apt update
sudo apt install avahi-daemon
sudo systemctl start avahi-daemon
sudo systemctl enable avahi-daemon

I allowed the container to communicate with the host’s Avahi daemon by:

  • Mounting the Avahi socket (/run/avahi-daemon/socket) into the container
  • Mounting the D-Bus socket (/var/run/dbus). Avahi needs this, apparently.
  • Running the container in privileged mode to allow necessary network operations. Else, I had to struggle with AppArmor. And I don’t really care for that.
  • Setting the environment variable ZEROCONF_BACKEND=avahi to tell Librespot to use Avahi for discovery.

As a result:

  • Librespot devices show up instantly in Spotify apps (it looks so cool to have KEF Speakers show up.)
  • Device switching is seamless without freezes or glitches
  • Playback control and metadata updates are quick and stable.

I’m happy.


My final docker-compose.yml

The device and format are specific to my SMSL Q5 Pro amplifier.

services:
  spotify-connect:
    image: giof71/librespot:latest
    container_name: spotify-connect
    network_mode: host
    privileged: true
    devices:
      - /dev/snd:/dev/snd
    volumes:
      - ./config:/user/config
      - ./data/cache:/data/cache
      - ./data/system-cache:/data/system-cache
      - /run/avahi-daemon/socket:/run/avahi-daemon/socket:ro # Mounted avahi
      - /var/run/dbus:/var/run/dbus:ro # Mounted dbus
    environment:
      - DEVICE=hw:CARD=AMP,DEV=0
      - FORMAT=S24_3
      - BACKEND=alsa
      - BITRATE=320
      - DEVICE_NAME=KEF Speakers
      - DEVICE_TYPE=speaker
      - VOLUME_CTRL=linear
      - ENABLE_CACHE=Y
      - ENABLE_SYSTEM_CACHE=Y
      - CACHE_SIZE_LIMIT=2G
      - AUTOPLAY=ON
      - ZEROCONF_BACKEND=avahi # Chose avahi instead of libmdns
    restart: unless-stopped
    healthcheck: # I am not even sure if this works. But I added it.
      test: ["CMD", "pgrep", "librespot"]
      interval: 1m
      timeout: 10s
      retries: 3