Container sound: ALSA or Pulseaudio
ALSA or Pulseaudio sound in docker container
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
.
ALSA
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.
Pulseaudio with shared socket
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.
Pulseaudio over TCP
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.
Pulseaudio as system wide daemon
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.