web-dev-qa-db-fra.com

exécuter des applications en utilisant l'audio dans un conteneur Docker

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;)

32
A. Binzxxxxxx

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:

  • vous pouvez gérer la plupart de cela (tous sans l'id utilisé) dans le dockerfile
  • en utilisant uid=$(id -u) pour obtenir l'ID utilisateur et le gid avec id -g
  • création d'un utilisateur docker avec cet identifiant

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
32
A. Binzxxxxxx

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).

  1. Installez paprefs sur votre système hôte, par exemple en utilisant Sudo apt-get install paprefs sur une machine Ubuntu.
  2. Lancez les préférences PulseAudio, accédez à l'onglet "Serveur réseau" et cochez la case "Activer l'accès réseau aux périphériques audio locaux" [1]
  3. Redémarrez votre ordinateur. (Seul le redémarrage de Pulseaudio n'a pas fonctionné pour moi sur Ubuntu 14.10)
  4. Installez Pulseaudio dans votre conteneur, par ex. Sudo apt-get install -y pulseaudio
  5. Dans votre conteneur, exécutez 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].
  6. C'est ça. L'étape 5 devrait probablement être automatisée si l'adresse IP et le port Pulseaudio sont susceptibles de changer. De plus, je ne sais pas si Docker stocke en permanence des variables d'environnement comme 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:

  1. Démarrez le conteneur avec -v /run/user/$UID/Pulse/native:/path/to/pulseaudio/socket
  2. Dans le conteneur, exécutez 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.

5
ctitze

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.

  1. Installer paprefs (sur la machine hôte):

    $ apt-get install paprefs
    
  2. Lancez paprefs (Préférences PulseAudio)> Serveur réseau> [X] Activez l'accès réseau aux périphériques audio locaux.

  3. Redémarrez PulseAudio:

    $ service pulseaudio restart
    
  4. 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 .

4
Wernight

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

Edit: How-To for ALSA and Pulseaudio in container

3
mviereck