在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)。
- 在主机系统上安装
paprefs
,例如在Ubuntu机器上使用sudo apt-get install paprefs
。 - 启动PulseAudio首选项,进入“networking服务器”选项卡,并勾选“启用对本地声音设备的networking访问”checkbox[1]
- 重启你的电脑。 (只有在Ubuntu 14.10上重新启动Pulseaudio才能工作)
- 在你的容器中安装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]。 您可以使用ifconfig
和Pulseaudio端口使用pax11publish
[1]find您的IP地址。 - 而已。 如果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套接字:
- 用
-v /run/user/$UID/pulse/native:/path/to/pulseaudio/socket
启动容器 - 在容器中,运行
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来使其安全。
-
安装paprefs (在主机上):
$ apt-get install paprefs
-
启动
paprefs
(PulseAudio首选项)>networking服务器> [X]启用对本地声音设备的networking访问。 -
重新启动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
。
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
- 找不到编辑器(编辑器path= / usr / bin /编辑器)运行visudo
- Docker / Selenium /无头Chrome:正确configurationSUID沙箱
- 2 Docker Container(JBOSS / DATABASE)之间的networking连接
- 无法从Docker容器内访问MacOSX主机上的端口
- 本地到远程复制超时或仅复制less量文档CouchDb
- 无法通过Ambari中pipe理员的默认login凭证进行login
- Docker + Django + MySQL – 非本地分区表的列表结束
- 无法将PhpStorm与Docker的xdebug连接起来
- 在Docker容器中使用Redis和mysql