This is a short tutorial on using podman to run X11 applications. This need often arises when one has to run X11 applications on distros such as Silverblue, when the application for instance has no Flatpak and one doesn't want to install the particular app on their host OS (for instance for Silverblue this process would result in the need to layer a package and then reboot, something which understandably would get quite irritating after a while).
For this tutorial, I will use the game Xonotic as the application to run inside the container. While there really is no need for this (with it having a Flatpak and all that) it's a good way of illustrating some things needed to run graphical applications, especially those that need hardware acceleration, from within a container.
The usual disclaimers about the insecurity of the X protocol apply. User caution is expected.
(The steps in this tutorial will work with rootless containers)
Now while the title of this tutorial doesn't mention it, we will need another
tool for this part. Say hello to buildah! We will use
buildah
to build our Xonotic-playing container.
This is done with the following command. For this tutorial, I'll be basing the container image on Fedora 29.
$ buildah from --name xonotic-container fedora:29
Now, there is something to pack on this. The --name
-switch allows us to name
this container image whatever we want. We could go without it, in which case
buildah
would give us a name to use, and print it to stdout
where we could
assign it to a shell variable, but I did it like this for my own convenience.
fedora:29
here tells us the container image we will be basing our image on. In
this case that image happens to be Fedora 29.
Now that we have an image we can play around with, it's time to install whatever we want on this container image.
$ buildah run xonotic-container -- /usr/bin/dnf install xonotic mesa-libGL mesa-dri-drivers
This command ought to be obvious, but if it's not, what we're doing is that we're installing some packages to our container image. In our case they're Xonotic, for fairly obvious reasons, and two mesa packages. These are so that we can run Xonotic later. More specifically, they're needed so that Xonotic can use our GPUs to display the carnage of this arena-shooting action.
This step can be extended so that user can install or pretty much do any preparations before the container is to be used. For instance they can create users, copy files from the host, et cetera.
After you've done all of the modifications your specific graphical app needs, it's time to commit your changes.
Now, some might tell you to delete files such as package manager metadata at this point, and I'm inclined to do the same, but this step is optional and depends on one's workflow and usage more than anything.
$ buildah run xonotic-container -- /usr/bin/dnf clean all
Now we're ready to commit the image.
$ buildah commit xonotic-container xonotic-container
The first argument is the container we've been working on at this point, and the second is the container image we're going to commit, and the name doesn't need to be the same as the first one. This commit-command will make our image available to podman
.
Now one could remove the image we've been working on by doing buildah rm xonotic-container
, but this again is optional. I personally like to leave the container be so I can update the image later. To update the image, one uses the package manager within the container like above, and then recommits the image.
Now we have our image. It's time to go to podman
. This step will not take as long as the last step. To run Xonotic in our new fancy container, all one has to do is the following.
$ podman run --rm -v /tmp/.X11-unix:/tmp/.X11-unix -v /dev/dri:/dev/dri --security-opt=label=type:container_runtime_t -e DISPLAY localhost/xonotic-container xonotic-glx
Phew. There is something to be unpacked here. So let's go from left to right.
--rm
tellspodman
to remove this container once it closes. This means that every time this command is ran, the container will be minty fresh.-v
tellspodman
to make a directory tree accessible inside the container instance. In this case we're making the/tmp/.X11-unix
and/dev/dri
accessible. The first one is to share the X11 socket with the container so we can run our app, and the second is to give our app access to the graphics card, which is needed for graphically accelerated graphics.--security-opt=label=type:container_runtime_t
tellspodman
to set the SELinux label of the container to becontainer_runtime_t
. This is needed so that our app can access the insides of/tmp/.X11-unix
and whatnot.-e
tellspodman
to set an environment variable for the process we're running. In this case we're setting the$DISPLAY
-variable so that the app inside the container can connect to our current X session.localhost/xonotic-container
is our container from earlier. This name can be checked by doingpodman images
.xonotic-glx
is our graphical app we want to run inside our container. In this case it's Xonotic.
Now as far as the performance of this example application inside the container is concerned, it's totally playable like it would be if we were using it on the host. Since we're not virtualising anything but simply imposing some limits on what our app can see, we get the same performance as "native".
I hope this small, two-step tutorial has helped some of you to understand how
container tools such as buildah
and podman
work and how they can be used to
run graphical applications.