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

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

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

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

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

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


person A. Binzxxxxxx    schedule 11.03.2015    source источник


Ответы (4)


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

мы начинаем с команды docker run 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: обновление
: может быть достаточно смонтировать сокет pulseaudio в контейнере с помощью опции -v. это зависит от вашей версии и предпочтительного метода доступа. см. другие ответы на метод сокета.

Здесь нам нужны в основном /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 переадресацией пользовательского интерфейса, как здесь: https://stackoverflow.com/a/28971413/2835523

Просто упомяну:

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

создать пользовательский скрипт:

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
person A. Binzxxxxxx    schedule 11.03.2015
comment
К сожалению, в 2014 году параметр --lxc-conf был удален. github.com/docker/docker/ тянуть / 5797 - person tu-Reinstate Monica-dor duh; 02.11.2016
comment
Я не тестировал, но думаю, есть замены для параметра. --privileged, --cap-add, -cgroup-parent и --device могут работать - person A. Binzxxxxxx; 02.11.2016
comment
-v / dev / snd: / dev / snd --privileged работает! Проверьте: github.com/pwasiewi/docker-freeciv-client - person 42n4; 19.04.2017
comment
У меня метод ALSA не работает. Я получаю следующую ошибку ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave. - person Vlad Firoiu; 08.05.2017
comment
Загружены ли модули snd (lsmod | grep snd)? Какие у вас карты (cat / proc / asound / cards)? Входит ли ваш пользователь в аудиогруппу (grep ^ audio / etc / group | grep $ USER)? вы также можете смонтировать эту конфигурацию [и попробовать по умолчанию использовать другую карту] (/etc/asound.conf) - person A. Binzxxxxxx; 09.05.2017
comment
Сработало у меня! Однако есть ли удача с Jack Audio? - person Ignorant; 11.10.2017
comment
Спасибо, заставил его работать как root, но я не могу заставить его работать с обычным пользователем. Любые идеи ? mplayer дает мне do_connect: could not connect to socket и connect: No such file or directory, а также серию Audio device got stuck... и без звука. - person bob dylan; 04.03.2019
comment
@bob это похоже на разрешение или отсутствие проблемы с монтированием. выяснить, какой файловый сокет он пытается открыть, например Strace. убедитесь, что он там, и у вас есть разрешение. большинство таких файлов находится в / tmp или где-то в / var, некоторые могут быть дома. - person A. Binzxxxxxx; 05.03.2019
comment
Для меня все действительно работало только с флагом --privileged (веб-камера, аудио) - person demaniak; 24.04.2020
comment
Как показывает другой ответ, для pulseaudio вам нужен только сокет (и файл cookie, если он работает с другим UID внутри) и НИЧЕГО больше. -1, до абсурда слишком сложно. - person Jan Hudec; 06.10.2020

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

  1. Установите paprefs в вашей хост-системе, например используя sudo apt-get install paprefs на машине Ubuntu.
  2. Запустите PulseAudio Preferences, перейдите на вкладку «Сетевой сервер» и установите флажок «Разрешить сетевой доступ к локальным звуковым устройствам» [1]
  3. Перезагрузите компьютер. (Только перезапуск Pulseaudio у меня не работал на Ubuntu 14.10)
  4. Установите Pulseaudio в свой контейнер, например sudo apt-get install -y pulseaudio
  5. В вашем контейнере запустите 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].
  6. Вот и все. Шаг 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

ОБНОВЛЕНИЕ (и, вероятно, лучшее решение):
Это также работает с использованием сокета Unix вместо сокета TCP:

  1. Запустите контейнер с -v /run/user/$UID/pulse/native:/path/to/pulseaudio/socket
  2. В контейнере запустите 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; Однако я не проверял это.

person ctitze    schedule 11.03.2015
comment
идея заключалась в том, чтобы заставить его работать без изменения настроек PulseAudio локали (и без использования сетевого подключения). но спасибо за информацию - person A. Binzxxxxxx; 27.03.2015
comment
Вам также необходимо настроить импульсный cookie, чтобы вы были авторизованы на хосте pulseaudio. По сути, -v $ HOME / .config / pulse / cookie: / run / pulse / cookie: ro или что-то в этом роде. Однако изменение $ PULSE_COOKIE для указания на / run / pulse / cookie у меня не сработало, потому что привязка доступна только для чтения, а затем pulse возвращается к ~ / .config / pulse / cookie. Итак, я сделал ln -fs / run / pulse / cookie ~ / .config / pulse / cookie и все. - person Petr Baudis; 30.05.2016
comment
Мне не требовалось сопоставление импульсного cookie. Возможно, потому что я уже запускал контейнер с хостом uid: gid? - person phs; 05.09.2020

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

  1. Установите paprefs (на хост-компьютере):

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

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

    $ service pulseaudio restart
    
  4. Убедитесь, что он работает, или перезагрузите компьютер:

    $ (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.

person Wernight    schedule 27.04.2015

Предполагая, что pulseaudio установлен на хосте и в изображении, можно обеспечить звук 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)

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

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

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

pactl unload-module $PULSE_MODULE_ID

Изменить: How-To для ALSA и Pulseaudio в контейнере

person mviereck    schedule 29.09.2016