Cette question est inspirée de Pouvez-vous exécuter des applications GUI dans un conteneur Docker? .
L'idée de base est d'exécuter des applications avec audio et interface utilisateur (vlc, firefox, skype, ...)
Je cherchais des conteneurs docker en utilisant pulseaudio mais tous les conteneurs que j'ai trouvés utilisaient le streaming pulseaudio sur tcp. (sandboxing de sécurité des applications)
Dans mon cas, je préférerais lire l'audio d'une application à l'intérieur du conteneur directement sur mon hôte pulseaudio. (sans tunnel ssh et images docker gonflées)
Pulseaudio car mon application qt l'utilise;)
il m'a fallu un certain temps avant de découvrir ce dont j'avais besoin. (Ubuntu)
nous commençons avec la commande docker run docker run -ti --rm myContainer sh -c "echo run something"
ALSA:
nous avons besoin de /dev/snd
et d'un accès matériel tel qu'il se présente. quand nous mettons cela ensemble, nous avons
docker run -ti --rm \
-v /dev/snd:/dev/snd \
--lxc-conf='lxc.cgroup.devices.allow = c 116:* rwm' \
myContainer sh -c "echo run something"`
Dans les nouvelles versions de docker sans drapeaux lxc, vous devez utiliser ceci:
docker run -ti --rm \
-v /dev/snd:/dev/snd \
--privileged \
myContainer sh -c "echo run something"`
PULSEAUDIO:
Ici, nous avons essentiellement besoin de /dev/shm
, /etc/machine-id
Et /run/user/$uid/Pulse
. Mais ce n'est pas tout (peut-être à cause d'Ubuntu et de la façon dont ils l'ont fait dans le passé). La variable d'environnement XDG_RUNTIME_DIR
Doit être la même dans le système hôte et dans votre conteneur Docker. Vous pouvez également avoir besoin de /var/lib/dbus
Car certaines applications accèdent à l'ID de machine à partir d'ici (ne contenant qu'un lien symbolique vers l'ID de machine "réel"). Et au moins, vous aurez peut-être besoin du dossier de départ masqué ~/.Pulse
Pour certaines données temporaires (je n'en suis pas sûr).
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"
Dans les nouvelles versions de docker, vous devrez peut-être ajouter --privileged
.
Bien sûr, vous pouvez combiner les deux ensemble et l'utiliser avec xServer
ui comme ici: https://stackoverflow.com/a/28971413/283552
Juste pour mentionner:
dockerfile
uid=$(id -u)
pour obtenir l'ID utilisateur et le gid avec id -g
créer un script utilisateur:
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
Inspiré par les liens que vous avez publiés, j'ai pu créer la solution suivante. Il est aussi léger que possible. Cependant, je ne sais pas s'il est (1) sécurisé et (2) correspond entièrement à votre cas d'utilisation (car il utilise toujours le réseau).
paprefs
sur votre système hôte, par exemple en utilisant Sudo apt-get install paprefs
sur une machine Ubuntu.Sudo apt-get install -y pulseaudio
export "Pulse_SERVER=tcp:<Host IP address>:<Host Pulseaudio port>"
. Par exemple, export "Pulse_SERVER=tcp:172.16.86.13:4713"
[2]. Vous pouvez trouver votre adresse IP en utilisant ifconfig
et le port Pulseaudio en utilisant pax11publish
[1].Pulse_SERVER
: Si ce n'est pas le cas, vous devez l'initialiser après chaque démarrage du conteneur.Des suggestions pour améliorer encore mon approche seraient grandement appréciées, car je travaille actuellement sur un problème similaire à celui de l'OP.
Les références:
[1] https://github.com/jlund/docker-chrome-pulseaudio
[2] https://github.com/jlund/docker-chrome-pulseaudio/blob/master/Dockerfile
MISE À JOUR (et probablement la meilleure solution):
Cela fonctionne également en utilisant un socket Unix au lieu d'un socket TCP:
-v /run/user/$UID/Pulse/native:/path/to/pulseaudio/socket
export "Pulse_SERVER=unix:/path/to/pulseaudio/socket"
Le /path/to/pulseaudio/socket
peut être n'importe quoi, à des fins de test, j'ai utilisé /home/user/Pulse
.
Peut-être que cela fonctionnera même avec le même chemin que sur l'hôte (en prenant soin de la partie $ UID) comme socket par défaut, de cette façon la solution ultime serait -v /run/user/$UID/Pulse/native:/run/user/<UID in container>/Pulse
; Je n'ai pas testé cela cependant.
Après avoir essayé la plupart des solutions décrites ici, j'ai trouvé que PulseAudio over network fonctionnait vraiment. Cependant, vous pouvez le sécuriser en conservant l'authentification.
Installer paprefs (sur la machine hôte):
$ apt-get install paprefs
Lancez paprefs
(Préférences PulseAudio)> Serveur réseau> [X] Activez l'accès réseau aux périphériques audio locaux.
Redémarrez PulseAudio:
$ service pulseaudio restart
Vérifiez que cela a fonctionné ou redémarrez la machine:
$ (pax11publish || xprop -root Pulse_SERVER) | grep -Eo 'tcp:[^ ]*'
tcp:myhostname:4713
Utilisez maintenant cette socket:
$ docker run \
-e Pulse_SERVER=tcp:$(hostname -i):4713 \
-e Pulse_COOKIE=/run/Pulse/cookie \
-v ~/.config/Pulse/cookie:/run/Pulse/cookie \
...
Vérifiez que l'utilisateur exécutant à l'intérieur du conteneur a accès au fichier cookie ~/.config/Pulse/cookie
.
Pour tester cela fonctionne:
$ apt-get install mplayer
$ mplayer /usr/share/sounds/alsa/Front_Right.wav
Pour plus d'informations, consultez le projet Docker Mopidy .
En supposant que pulseaudio est installé sur l'hôte et dans l'image, on peut fournir le son pulseaudio sur tcp en quelques étapes seulement. pulseaudio n'a pas besoin d'être redémarré et aucune configuration ne doit être effectuée sur l'hôte ou dans l'image non plus. De cette façon, il est inclus dans x11docker , sans avoir besoin de VNC ou SSH:
Tout d'abord, trouver un port tcp gratuit :
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
Obtenez l'adresse IP du démon docker. Je trouve toujours que c'est 172.17.42.1/16
ip -4 -o a | grep docker0 | awk '{print $4}'
Charger le module tcp pulseaudio, authentifier la connexion à docker ip:
Pulse_MODULE_ID=$(pactl load-module module-native-protocol-tcp port=$Pulse_PORT auth-ip-acl=172.17.42.1/16)
Lors de l'exécution de docker, créez la variable d'environnement Pulse_SERVER
docker run -e Pulse_SERVER=tcp:172.17.42.1:$Pulse_PORT yourimage
Ensuite, déchargez le module TCP. (Remarque: pour des raisons inconnues, le déchargement de ce module peut arrêter le démon pulseaudio sur l'hôte):
pactl unload-module $Pulse_MODULE_ID