Установка — Docker Compose
Требования
Заголовок раздела «Требования»- Docker Engine и Docker Compose
- Bluetooth-адаптер на хосте
- PulseAudio или PipeWire на хосте
- Music Assistant в вашей сети
Публикуемый образ поддерживает linux/amd64, linux/arm64 и linux/arm/v7.
Быстрый старт
Заголовок раздела «Быстрый старт»-
Сначала сопрягите колонку на хосте
Окно терминала bluetoothctlscan onpair AA:BB:CC:DD:EE:FFtrust AA:BB:CC:DD:EE:FFconnect AA:BB:CC:DD:EE:FFexit -
Создайте
.envAUDIO_UID=1000AUDIO_GID=1000TZ=Europe/MoscowWEB_PORT=8080BASE_LISTEN_PORT=8928 -
Создайте
docker-compose.ymlservices:sendspin-client:image: ghcr.io/trudenboy/sendspin-bt-bridge:latestcontainer_name: sendspin-clientrestart: unless-stoppednetwork_mode: hostvolumes:- /var/run/dbus:/var/run/dbus- /run/user/${AUDIO_UID:-1000}/pulse:/run/user/${AUDIO_UID:-1000}/pulse- /run/user/${AUDIO_UID:-1000}/pipewire-0:/run/user/${AUDIO_UID:-1000}/pipewire-0- /etc/docker/Sendspin:/configenvironment:- SENDSPIN_SERVER=auto- TZ=${TZ:-UTC}- WEB_PORT=${WEB_PORT:-8080}- BASE_LISTEN_PORT=${BASE_LISTEN_PORT:-8928}- CONFIG_DIR=/config- AUDIO_UID=${AUDIO_UID:-1000}- AUDIO_GID=${AUDIO_GID:-1000}- PULSE_SERVER=unix:/run/user/${AUDIO_UID:-1000}/pulse/native- XDG_RUNTIME_DIR=/run/user/${AUDIO_UID:-1000}devices:- /dev/bus/usb:/dev/bus/usbcap_add:- NET_ADMIN- NET_RAW -
Запустите контейнер
Окно терминала mkdir -p /etc/docker/Sendspindocker compose up -d -
Откройте веб-интерфейс
http://<ip-хоста>:<WEB_PORT>
Планирование портов
Заголовок раздела «Планирование портов»WEB_PORTуправляет прямым listener’ом веб-интерфейса/API в Docker-режиме.BASE_LISTEN_PORTзадаёт базовый Sendspin-порт для устройств без явногоlisten_port.- Каждое устройство без ручного порта получает
BASE_LISTEN_PORT + индекс_устройства. - В сложных схемах можно задать
listen_portиlisten_hostна уровне устройства через веб-интерфейс или/config/config.jsonпосле первого запуска.
Пример блока устройства в /config/config.json:
{ "mac": "11:22:33:44:55:66", "player_name": "Колонка на кухне", "listen_port": 8935, "listen_host": "192.168.1.50"}listen_host меняет только рекламируемый host/IP для плеера и не влияет на bind-адрес внутри контейнера.
Несколько bridge-контейнеров на одном хосте
Заголовок раздела «Несколько bridge-контейнеров на одном хосте»Если вы запускаете несколько bridge-контейнеров на одной машине:
- задайте каждому контейнеру уникальный
WEB_PORT - задайте каждому контейнеру уникальный
BASE_LISTEN_PORT - не настраивайте одну и ту же Bluetooth-колонку в двух работающих контейнерах
Сеть и capabilities
Заголовок раздела «Сеть и capabilities»network_mode: host обязателен для:
- mDNS-обнаружения при
SENDSPIN_SERVER=auto - доступа к Bluetooth-стеку хоста через D-Bus
Необходимые capabilities:
| Capability | Назначение |
|---|---|
NET_ADMIN | Управление Bluetooth-адаптером |
NET_RAW | Raw Bluetooth/HCI socket access |
Проверка контейнера
Заголовок раздела «Проверка контейнера»docker logs -f sendspin-clientcurl -s http://localhost:${WEB_PORT:-8080}/api/preflight | python3 -m json.toolВ новых образах startup diagnostics также показывают:
- init UID/GID внутри контейнера
- app UID/GID запущенного bridge-процесса
- выбранный путь к audio socket
- владельца/права сокета
- результат живого
pactl infoprobe - пришлось ли контейнеру подождать позднюю готовность D-Bus / Bluetooth / audio при холодном старте хоста
- отдельное предупреждение, если bridge-процесс работает под другим UID, чем user-scoped audio socket на хосте
Если у вас уже настроены Bluetooth-устройства, новые образы также недолго ждут позднего появления host-зависимостей перед запуском bridge-процесса. Это убирает частый race, когда после перезагрузки хоста контейнеру нужен ещё один ручной restart.
Если хост стартует особенно медленно, ожидание можно подстроить:
environment: - STARTUP_DEPENDENCY_WAIT_ATTEMPTS=60 - STARTUP_DEPENDENCY_WAIT_DELAY_SECONDS=1Troubleshooting для user-scoped PipeWire / PulseAudio
Заголовок раздела «Troubleshooting для user-scoped PipeWire / PulseAudio»Если на хосте аудио работает нормально, но в контейнере всё ещё видно Connection refused или pactl не может подключиться, проверьте:
docker exec sendspin-client ls -la /run/user/${AUDIO_UID:-1000}/pulse/docker exec sendspin-client env | grep -E 'PULSE|XDG'docker exec sendspin-client ps -o user:20,pid,command -C python3docker inspect sendspin-client --format '{{json .Mounts}}'И на хосте:
idpactl infols -la /run/user/${AUDIO_UID:-1000}/pulse/Если аудио всё ещё не работает, сначала убедитесь по startup diagnostics, что App UID совпадает с UID вашего host audio user. Старый глобальный Compose user: override теперь нужен только как временный диагностический тест для старых образов:
services: sendspin-client: user: "${AUDIO_UID:-1000}:${AUDIO_UID:-1000}"После этого перезапустите контейнер и проверьте, начал ли работать pactl. Это именно шаг диагностики: он помогает быстро подтвердить проблему несовпадения UID/session при доступе к host audio socket.
Применение изменений конфигурации
Заголовок раздела «Применение изменений конфигурации»Изменения устройств, адаптеров, WEB_PORT, BASE_LISTEN_PORT и настроек подключения к Music Assistant требуют перезапуска контейнера.