Run any application on RHEL7 containerized with 3D acceleration and pulseaudio ( Steam, Pidgin, VLC, …)

Red Hat Enterprise Linux 7 RC was released some time ago. Since the beta was already quite decent I wanted to toy around with the RC version.

My setup is quite unique. My root filesystem is on ZFS which I used on archlinux. Since I didn’t want to reinstall my laptop I just created another ZFS filesystem and manually bootstrapped RHEL7 with the RPMs from ftp://ftp.redhat.com and the version of yum which can be found in the archlinux user repository.
I will not go into the specifics of that though.

The overall experience with RHEL7 has been great so far. But I was missing some applications like Pidgin ( which has been removed in favour of Telepathy ), Steam and VLC.
Since I know my way around systemd, thanks to archlinux and Fedora I knew about systemd-nspawn.
It’s a tool to enable lightweight containerisation of single applications or booting whole Linux distributions in their own namespace.

So getting the Pidgin from my archlinux install running was quite easy.
sudo systemd-nspawn -M pidgin --bind=/home:/home -D /altroot/ARCH-ROOT su maci -c 'DISPLAY=:0 pidgin' &

Another great way to run applications in containers is Docker.
Docker has a great index of pre-built images to start applications in containers.
There even is an image to run Steam inside of a SteamOS environment. https://index.docker.io/u/tianon/steam/
In theory a simple docker run tianon/steam should be sufficient to boot up steam.
However Steam needs access to the hosts X server. So we need to bind-mount /tmp/.X11-unix into the docker container. Docker has a command line option for that -v its the equivalent to systemd-nspawn‘s --bind.
Now the Steam interface starts up just fine. There is no audio output though.
It took me some time to get the audio output working since the pulseaudio FAQ is quite outdated, it lists a bunch of bind mounts required to get audio working inside a chroot environment.
In reality what we do need is /run/user/${UID}/pulse, /etc/machine-id and /dev/shm.

Now we got graphical output and sound, but the 3D acceleration is not working.
It’s easy to get it working though. First make sure the OS image you use has the opengl libs for your physical video card, in the steam container the mesa libs are pre-installed, next bind mount /dev/dri into your container.

Update 2015-10-04: For some reason the image does not work out of the box anymore, I will investigate.

All combined we get something like:
docker run --name=steam \
-v /dev/dri:/dev/dri \
-v /tmp/.X11-unix:/tmp/.X11-unix -v /dev/shm:/dev/shm \
-v /run/user/${UID}/pulse:/run/user/${UID}/pulse \
-v /etc/machine-id:/etc/machine-id \
-v ${HOME}/Downloads:/tmp/Downloads \
-e DISPLAY=${DISPLAY} tianon/steam

Further information about the parameters can be found in the docker documentation.

That’s all. Using the methods described above you can get almost every application working in a container. VLC for example with systemd-nspawn
sudo systemd-nspawn --bind /tmp/.X11-unix:/tmp/.X11-unix \
--bind=/dev/shm:/dev/shm --bind=/dev/dri:/dev/dri \
--bind=/run/user/${UID}/pulse:/run/user/${UID}/pulse \
--bind=/etc/machine-id:/etc/machine-id \
-D /altroot/ARCH-ROOT \
su vlc -c "DISPLAY=:0 QT_X11_NO_MITSHM=1 dbus-launch /usr/bin/vlc --no-qt-privacy-ask"

Other ideas for applications you can run in a container: firefox, keepassX or basically every desktop application you want to separate from the system.
But you should remember to only bind-mount those resources into the container which are mandatory for your application to work.

Advertisements

10 thoughts on “Run any application on RHEL7 containerized with 3D acceleration and pulseaudio ( Steam, Pidgin, VLC, …)

    1. maci0 Post author

      I think RedHat is on their way of doing so with Project Atomic and the new Openshift+Docker integration.

      Reply
  1. Frank Kaufmann (@FrankKaufmann76)

    Do you know what packages are required to be able to nspawn to a different Arch Linux root directory on your filesystem? The wiki recommends just pacstraping “base” to some folder [pacstrap -i -c -d ~/MyContainer base] and leaving out “linux” since you still use your local kernel. This still pulls in packages from [core], which probably aren’t strictly needed to have a bear minimum container.

    Reply
    1. maci0 Post author

      I would guess the bare minimum you would need is bash systemd pacstrap should pull in all the dependencies those two have.
      You might even get away with a smaller shell like busybox or dash.

      Reply
      1. Frank Kaufmann (@FrankKaufmann76)

        Thanks that worked. However systemd + dependencies is already ~200 MB. Maybe I’ll try installing a modified systemd package, that is also stripped down to the bear minimum. glibc is also kind of big on its own.

  2. rhn

    I found that binding /dev/dri inside a Docker container doesn’t work perfectly – the program in the container gets permission denied and relies on llvmpipe instead. Can the container share devices from host?

    Reply
    1. maci0 Post author

      The impact on performance is negligible.
      And yes, using this method it is possible to run steam in a docker container.
      In fact there are some Dockerfiles floating around for steam/steamos.

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s