web-dev-qa-db-ja.com

Dockerコンテナでオーディオを使用してアプリを実行する

この質問は GUIアプリをdockerコンテナで実行できますか? に触発されています。

基本的な考え方は、オーディオとUI(vlc、firefox、skypeなど)を使用してアプリを実行することです

Pulseaudioを使用してdockerコンテナーを検索していましたが、tcpでpulseaudioストリーミングを使用しているすべてのコンテナーを見つけました。 (アプリケーションのセキュリティサンドボックス化)

私の場合、コンテナ内のアプリからホストpulseaudioに直接オーディオを再生することを好みます。 (sshトンネリングおよび肥大化したDockerイメージなし)

Pulseaudioは私のqtアプリが使用しているためです;)

32
A. Binzxxxxxx

必要なものが見つかるまで時間がかかりました。 (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バージョンでは、これを使用する必要があります:

_docker run -ti --rm \
    -v /dev/snd:/dev/snd \
     --privileged \
    myContainer sh -c "echo run something"`
_

パルスオーディオ:
ここでは、基本的に_/dev/shm_、_/etc/machine-id_、_/run/user/$uid/Pulse_が必要です。しかし、それだけではありません(おそらく、Ubuntuと過去のやり方によるものでしょう)。環境変数_XDG_RUNTIME_DIR_は、ホストシステムとdockerコンテナで同じである必要があります。一部のアプリはここからマシンIDにアクセスしているため、_/var/lib/dbus_も必要になる場合があります(「実際の」マシンIDへのシンボリックリンクのみが含まれる場合があります)。また、少なくとも一時データには隠しホームフォルダー_~/.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 -g_でユーザーIDとgidを取得します
  • このIDでdockerユーザーを作成する

ユーザースクリプトの作成:

_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

あなたが投稿したリンクに触発されて、次のソリューションを作成することができました。それは私がそれを得ることができるのと同じくらい軽量です。ただし、(1)安全であり、(2)ユースケースに完全に適合するかどうかはわかりません(まだネットワークを使用しているため)。

  1. ホストシステムにpaprefsをインストールします。 UbuntuマシンでSudo apt-get install paprefsを使用します。
  2. PulseAudioの設定を起動し、[ネットワークサーバー]タブに移動して、[ローカルサウンドデバイスへのネットワークアクセスを有効にする]チェックボックスをオンにします[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を使用してIPアドレスを確認し、pax11publish [1]を使用してPulseaudioポートを確認できます。
  6. それでおしまい。 IPアドレスとPulseaudioポートが変更される可能性がある場合、ステップ5はおそらく自動化されるはずです。さらに、DockerがPulse_SERVERのような環境変数を永続的に保存するかどうかもわかりません。そうでない場合は、各コンテナーの起動後に初期化する必要があります。

私は現在、OPと同様の問題に取り組んでいるので、私のアプローチをさらに改善するための提案をいただければ幸いです。

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

更新(そしておそらくより良い解決策):
これは、TCPソケットの代わりにUnixソケットを使用しても機能します。

  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です;ただし、これはテストしていません。

5
ctitze

ここで説明したほとんどのソリューションを試してみたところ、実際に機能しているのは PulseAudio over network だけでした。ただし、認証を保持することで安全にできます。

  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 プロジェクトを確認してください。

4
Wernight

ホストおよびイメージにpulseaudioがインストールされていると仮定すると、わずかな手順でtcp経由でpulseaudioサウンドを提供できます。 pulseaudioを再起動する必要はなく、ホストまたはイメージで設定を行う必要もありません。このように、VNCやSSHを必要とせずに、 x11docker に含まれています。

まず、 無料の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 -o a | grep docker0 | awk '{print $4}'

Pulseaudio tcpモジュールをロードし、docker ipへの接続を認証します:

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

Dockerの実行時に、環境変数Pulse_SERVERを作成します

docker run -e Pulse_SERVER=tcp:172.17.42.1:$Pulse_PORT yourimage

その後、tcpモジュールをアンロードします。 (注:不明な理由により、このモジュールをアンロードすると、ホストのpulseaudioデーモンが停止する場合があります):

pactl unload-module $Pulse_MODULE_ID

編集: コンテナ内のALSAおよびPulseaudioの使用方法

3
mviereck