Skip to content

Instantly share code, notes, and snippets.

@sham1
Created October 14, 2018 20:38
Show Gist options
  • Save sham1/aa451608775d36fb55ebdbbc955bcb4d to your computer and use it in GitHub Desktop.
Save sham1/aa451608775d36fb55ebdbbc955bcb4d to your computer and use it in GitHub Desktop.

Revisions

  1. sham1 created this gist Oct 14, 2018.
    94 changes: 94 additions & 0 deletions x11_container_tutorial.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    # Running X11 applications using Podman

    This is a short tutorial on using [podman](https://podman.io/) 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](https://www.xonotic.org/) 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)

    ## Step 1. Building the image

    Now while the title of this tutorial doesn't mention it, we will need another
    tool for this part. Say hello to [buildah](https://buildah.io/)! We will use
    `buildah` to build our Xonotic-playing container.

    ### Step 1.1. Create a new image

    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.

    ### Step 1.2. Installing packages

    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.

    ### Step 1.3. Committing the image

    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.

    ## Step 2. Running the application

    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` tells `podman` to remove this container once it closes. This means that every time this command is ran, the container will be minty fresh.
    * `-v` tells `podman` 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` tells `podman` to set the SELinux label of the container to be `container_runtime_t`. This is needed so that our app can access the insides of `/tmp/.X11-unix` and whatnot.
    * `-e` tells `podman` 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 doing `podman 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.