在Docker容器中使用audio运行应用程序

这个问题的启发可以在docker容器中运行GUI应用程序吗? 。

基本的想法是运行audio和用户界面(VLC,火狐,Skype,…)

我正在使用pulseaudiosearchdocker容器,但是我发现使用pulseaudio streaming over tcp的所有容器。 (应用程序的安全沙箱)

  • https://gist.github.com/hybris42/ce429de428e5af3a344a
  • https://github.com/jlund/docker-chrome-pulseaudio
  • https://github.com/tomparys/docker-skype-pulseaudio

在我的情况下,我会prefere播放audio从容器内的应用程序直接到我的主机pulseaudio。 (没有SSH隧道和臃肿的docker图像)

Pulseaudio,因为我的qt应用程序正在使用它;)

我花了一些时间,直到我发现需要什么。 (Ubuntu的)

我们先用docker run -ti --rm myContainer sh -c "echo run something" 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版本中,你应该使用这个:

 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,以及他们过去是如何做的)。 环境variablesXDG_RUNTIME_DIR必须在主机系统和XDG_RUNTIME_DIR容器中相同。 您可能还需要/var/lib/dbus因为有些应用程序正在从这里访问机器标识(可能只包含“真实”机器标识的符号链接)。 至less你可能需要隐藏的家庭文件夹~/.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" 

在新的docker版本中,您可能需要添加 – --privileged
当然,您可以将它们结合在一起,并像下面这样使用xServer ui转发: https : //stackoverflow.com/a/28971413/2835523

只要提一下:

  • 您可以在dockerfile处理大部分(全部没有使用的id)
  • 使用uid=$(id -u)获取用户ID和gid与id -g
  • 用这个ID创build一个docker用户

创build用户脚本:

 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 

受到您发布的链接的启发,我可以创build以下解决scheme。 它是尽可能轻,我可以得到它。 但是,我不确定它是否(1)安全,(2)完全适合您的使用情况(因为它仍然使用networking)。

  1. 在主机系统上安装paprefs ,例如在Ubuntu机器上使用sudo apt-get install paprefs
  2. 启动PulseAudio首选项,进入“networking服务器”选项卡,并勾选“启用对本地声音设备的networking访问”checkbox[1]
  3. 重启你的电脑。 (只有在Ubuntu 14.10上重新启动Pulseaudio才能工作)
  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]。 您可以使用ifconfig和Pulseaudio端口使用pax11publish [1]find您的IP地址。
  6. 而已。 如果IP地址和Pulseaudio端口可能会更改,则步骤5应该可以自动进行。 另外,我不确定Docker是否会永久存储像PULSE_SERVER这样的环境variables:如果没有,那么在每个容器启动之后你必须初始化它。

build议使我的方法更好,将不胜感激,因为我目前正在处理与OP类似的问题。

参考文献:
[1] https://github.com/jlund/docker-chrome-pulseaudio
[2] https://github.com/jlund/docker-chrome-pulseaudio/blob/master/Dockerfile

更新(也许更好的解决scheme):
这也使用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可以是任何东西,用于testing目的我使用/home/user/pulse
也许它甚至可以在主机上使用相同的path(照顾$ UID部分)作为默认套接字,这样最终的解决scheme将是-v /run/user/$UID/pulse/native:/run/user/<UID in container>/pulse ; 但是我没有testing过这个。

在尝试了大部分这里描述的解决scheme后,我发现只有PulseAudio通过networking才能真正起作用。 但是,您可以通过保持身份validation来使其安全。

  1. 安装paprefs (在主机上):

     $ apt-get install paprefs 
  2. 启动paprefs (PulseAudio首选项)>networking服务器> [X]启用对本地声音设备的networking访问。

  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

testing它的作品:

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

有关更多信息,请查看Docker Mopidy项目。

假设pulseaudio安装在主机和图像上,可以通过几个步骤在tcp上提供pulseaudio声音。 pulseaudio不需要重新启动,也不需要在主机或图像上进行configuration。 这样它就被包含在x11docker中 ,而不需要VNC或SSH:

首先find一个免费的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 

获取docker守护进程的ip地址。 我总是发现它是172.17.42.1/16

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

加载pulseaudio tcp模块,authentication连接到docker ip:

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

在docker运行,创build环境variablesPULSE_SERVER

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

之后,卸载TCP模块。 (注意:由于未知的原因,卸载这个模块可以阻止主机上的pulseaudio守护进程):

 pactl unload-module $PULSE_MODULE_ID