Запускать приложения с помощью аудио в контейнере докеров
Этот вопрос вдохновлен Можете ли вы запускать графические приложения в контейнере докеров?.
Основная идея - запустить приложения с аудио и 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