Запускать приложения с помощью аудио в контейнере докеров

Этот вопрос вдохновлен Можете ли вы запускать графические приложения в контейнере докеров?.

Основная идея - запустить приложения с аудио и ui (vlc, firefox, skype,...)

Я искал контейнеры для докеров, используя pulseaudio, но все контейнеры, которые я нашел, с использованием импульсного потока через tcp. (безопасная песочница приложений)

В моем случае я предпочел бы воспроизводить звук из приложения внутри контейнера непосредственно на мой хост pulseaudio. (без туннелей ssh ​​и раздутых изображений докеров)

Pulseaudio, потому что мое приложение Qt использует его;)

Ответ 1

мне потребовалось некоторое время, пока я не узнал, что нужно. (Ubuntu)

мы начинаем с команды запуска docker docker run -ti --rm myContainer sh -c "echo run something"

ALSA:
нам нужно /dev/snd и некоторый доступ к оборудованию, как он выглядит. когда мы ставим это вместе, имеем

docker run -ti --rm \
    -v /dev/snd:/dev/snd \
    --lxc-conf='lxc.cgroup.devices.allow = c 116:* rwm' \
    myContainer sh -c "echo run something"`

В новых версиях докеров без флагов lxc вы используете это:

docker run -ti --rm \
    -v /dev/snd:/dev/snd \
     --privileged \
    myContainer sh -c "echo run something"`

PulseAudio:
Здесь нам нужны в основном /dev/shm, /etc/machine-id и /run/user/$uid/pulse. Но это еще не все (возможно, из-за Ubuntu и как они это делали в прошлом). Переменная окружения XDG_RUNTIME_DIR должна быть одинаковой в хост-системе и в контейнере докера. Вам также может понадобиться /var/lib/dbus, потому что некоторые приложения получают доступ к идентификатору машины здесь (может содержать только символическую ссылку на "реальный" идентификатор машины). И по крайней мере вам может понадобиться скрытая домашняя папка ~/.pulse для некоторых временных данных (я не уверен в этом).

docker run -ti --rm \
    -v /dev/shm:/dev/shm \
    -v /etc/machine-id:/etc/machine-id \
    -v /run/user/$uid/pulse:/run/user/$uid/pulse \
    -v /var/lib/dbus:/var/lib/dbus \
    -v ~/.pulse:/home/$dockerUsername/.pulse \
    myContainer sh -c "echo run something"

В новых версиях докеров вам может понадобиться добавить --privileged.
Конечно, вы можете комбинировать оба вместе и использовать их вместе с xServer ui forwarding, как здесь: fooobar.com/questions/27380/...

Просто чтобы упомянуть:

  • вы можете обрабатывать большую часть этого (все без использованного идентификатора) в dockerfile
  • используя uid=$(id -u), чтобы получить идентификатор пользователя и gid с помощью id -g
  • создание пользователя-докера с помощью этого id

создать пользователя script:

mkdir -p /home/$dockerUsername && \
echo "$dockerUsername:x:${uid}:${gid}:$dockerUsername,,,:/home/$dockerUsername:/bin/bash" >> /etc/passwd && \
echo "$dockerUsername:x:${uid}:" >> /etc/group && \
mkdir /etc/sudoers.d && \
echo "$dockerUsername ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$dockerUsername && \
chmod 0440 /etc/sudoers.d/$dockerUsername && \
chown ${uid}:${gid} -R /home/$dockerUsername

Ответ 2

Вдохновленный ссылками, которые вы опубликовали, я смог создать следующее решение. Это так же легко, как и я. Однако я не уверен, что он (1) безопасен и (2) полностью соответствует вашему прецеденту (поскольку он все еще использует сеть).

  • Установите paprefs на вашу хост-систему, например. используя sudo apt-get install paprefs на машине Ubuntu.
  • Запустите настройки PulseAudio, перейдите на вкладку "Сетевой сервер" и установите флажок "Включить сетевой доступ к локальным звуковым устройствам" [1]
  • Перезагрузите компьютер. (Только перезапуск Pulseaudio не работал у меня на Ubuntu 14.10)
  • Установите Pulseaudio в свой контейнер, например. sudo apt-get install -y pulseaudio
  • В контейнере запустите export "PULSE_SERVER=tcp:<host IP address>:<host Pulseaudio port>". Например, export "PULSE_SERVER=tcp:172.16.86.13:4713" [2]. Вы можете узнать свой IP-адрес, используя ifconfig и порт Pulseaudio, используя pax11publish [1].
  • Что это. Шаг 5 должен, вероятно, быть автоматическим, если IP-адрес и порт Pulseaudio могут быть изменены. Кроме того, я не уверен, что Docker постоянно сохраняет переменные окружения, такие как PULSE_SERVER: если это не так, вы должны инициализировать его после запуска каждого контейнера.

Предложения, чтобы сделать мой подход еще лучше, будут очень благодарны, так как я сейчас работаю над аналогичной проблемой, как OP.

Литература:
[1] https://github.com/jlund/docker-chrome-pulseaudio
[2] https://github.com/jlund/docker-chrome-pulseaudio/blob/master/Dockerfile

UPDATE (и, вероятно, лучшее решение):
Это также работает с использованием Unix-сокета вместо TCP-сокета:

  • Запустите контейнер с помощью -v /run/user/$UID/pulse/native:/path/to/pulseaudio/socket
  • В контейнере запустите export "PULSE_SERVER=unix:/path/to/pulseaudio/socket"

/path/to/pulseaudio/socket может быть любым, для целей тестирования я использовал /home/user/pulse.
Возможно, он будет работать даже по тому же пути, что и на хосте (заботясь о части $UID) в качестве сокета по умолчанию, таким образом, окончательное решение будет -v /run/user/$UID/pulse/native:/run/user/<UID in container>/pulse; Однако я не тестировал это.

Ответ 3

Попробовав большинство описанных здесь решений, я обнаружил, что действительно работает PulseAudio через сеть. Однако вы можете сделать это безопасным, сохранив аутентификацию.

  • Установите paprefs (на хост-машине):

    $ apt-get install paprefs
    
  • Запуск paprefs (Настройки PulseAudio) > Сетевой сервеp > [X] Включить сетевой доступ к локальным звуковым устройствам.

  • Перезапустите PulseAudio:

    $ service pulseaudio restart
    
  • Проверьте, работает ли он или перезагружается машина:

    $ (pax11publish || xprop -root PULSE_SERVER) | grep -Eo 'tcp:[^ ]*'
    tcp:myhostname:4713
    

Теперь используйте этот сокет:

$ docker run \
    -e PULSE_SERVER=tcp:$(hostname -i):4713 \
    -e PULSE_COOKIE=/run/pulse/cookie \
    -v ~/.config/pulse/cookie:/run/pulse/cookie \
    ...

Убедитесь, что пользователь, работающий внутри контейнера, имеет доступ к файлу файла cookie ~/.config/pulse/cookie.

Для проверки работы:

$ apt-get install mplayer
$ mplayer /usr/share/sounds/alsa/Front_Right.wav

Для получения дополнительной информации можно проверить проект Docker Mopidy.

Ответ 4

Предполагая, что pulseaudio установлен на хосте и на изображении, можно обеспечить импульсное звучание через tcp всего несколькими шагами. pulseaudio не нужно перезапускать, и настройка не должна выполняться на хосте или в изображении. Таким образом, он включен в x11docker, без необходимости использования VNC или SSH:

Сначала найдите свободный порт tcp:

read LOWERPORT UPPERPORT < /proc/sys/net/ipv4/ip_local_port_range
while : ; do
  PULSE_PORT="`shuf -i $LOWERPORT-$UPPERPORT -n 1`"
  ss -lpn | grep -q ":$PULSE_PORT " || break
done

Получить IP-адрес демона докеров. Я всегда считаю, что это 172.17.42.1/16

ip -4 -o a | grep docker0 | awk '{print $4}'

Загрузите модуль pulseaudio tcp, выполните аутентификацию соединения с докере ip:

PULSE_MODULE_ID=$(pactl load-module module-native-protocol-tcp port=$PULSE_PORT auth-ip-acl=172.17.42.1/16)

При запуске docker создайте переменную окружения PULSE_SERVER

docker run -e PULSE_SERVER=tcp:172.17.42.1:$PULSE_PORT yourimage

Затем выгрузите модуль tcp. (Примечание: по неизвестным причинам выгрузка этого модуля может остановить демон pulseaudio на хосте):

pactl unload-module $PULSE_MODULE_ID