-
Notifications
You must be signed in to change notification settings - Fork 377
Container sound: ALSA or Pulseaudio
This page describes three possible ways how to set up sound for docker containers without x11docker. Most common is the easy ALSA setup. A bit more advanced, but with better integration in most desktop environments is a setup with Pulseaudio.
Pulseaudio can be provided with shared unix sockets or with a TCP connection.
Both ways need Pulseaudio server on host and Pulseaudio client library (Debian: libpulse0
) in image. x11docker supports both ways with --pulseaudio=socket
or --pulseaudio=tcp
.
For ALSA sound just share sound devices with --device /dev/snd
. You would not need the more advanced Pulseaudio setup, but will have trouble if more than one application tries to access the sound hardware. x11docker provides this setup with option --alsa
.
- If you have an unprivileged user in container, add him to group
audio
with--group-add=audio
. - If you can't hear sound, you might need to set environment variable
--env ALSA_CARD=Generic
or another card name that shows up inaplay -l
. - To check ALSA sound in container, install
alsa-utils
in image and runspeaker-test
:docker run --rm --device /dev/snd ALSAIMAGE speaker-test
- Applications that only support Pulseaudio can be fooled with apulse. Example:
apulse firefox
sets up a fake Pulseaudio environment, but forwards the sound signals to ALSA.
Create pulseaudio socket:
pactl load-module module-native-protocol-unix socket=/tmp/pulseaudio.socket
Create /tmp/pulseaudio.client.conf
for pulseaudio clients:
default-server = unix:/tmp/pulseaudio.socket
# Prevent a server running in the container
autospawn = no
daemon-binary = /bin/true
# Prevent the use of shared memory
enable-shm = false
Share socket and config file with docker and set environment variables PULSE_SERVER
and PULSE_COOKIE
. Container user must be same as on host:
docker run --rm \
--env PULSE_SERVER=unix:/tmp/pulseaudio.socket \
--env PULSE_COOKIE=/tmp/pulseaudio.cookie \
--volume /tmp/pulseaudio.socket:/tmp/pulseaudio.socket \
--volume /tmp/pulseaudio.client.conf:/etc/pulse/client.conf \
--user $(id -u):$(id -g) \
imagename
The cookie will be created by pulseaudio itself.
Get IP address from host:
# either an arbitrary IPv4 address from host
Hostip="$(ip -4 -o a | awk '{print $4}' | cut -d/ -f1 | grep -v 127.0.0.1 | head -n1)"
# or especially IP from docker daemon
Hostip="$(ip -4 -o a| grep docker0 | awk '{print $4}' | cut -d/ -f1)"
Run docker image. You need a free TCP port, here 34567 is used. (TCP port number must be in range of cat /proc/sys/net/ipv4/ip_local_port_range
and must not be in use. Check with ss -nlp | grep 34567
.)
docker run --rm \
--name pulsecontainer \
--env PULSE_SERVER=tcp:$Hostip:34567 \
imagename
After docker run [...]
get IP of container with:
Containerip="$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' pulsecontainer)"
Load pulseaudio TCP module authenticated with container IP:
pactl load-module module-native-protocol-tcp port=34567 auth-ip-acl=$Containerip
Be aware that the TCP module is loaded after container is up and running. It takes a moment until pulseaudio server is available for container applications. If TCP connection fails, check for possible iptables
and ufw
settings that might prohibit the connection.
If pulseaudio runs as a system wide daemon on host, LC_ALL=C pactl info
shows Server String: /var/run/pulse/native
and User Name: pulse
.
Note that such a setup is discouraged.
- By default pulseaudio runs under an unprivileged user.
- If pulseaudio runs as a system wide daemon, the TCP setup works.
- To share the system socket
/var/run/pulse/native
, the container user must be added to grouppulse-access
with--group-add pulse-access
.PULSE_COOKIE
is not needed in that case.