Skip to main content

It’s no secret that the preferred way of obtaining new end-user software in Nitrux is to use AppImages, although we also support Flatpak. That is because we’d prefer to keep the root clean and without surprises; in other words, we don’t make this distribution centered around a package manager but rather applications. Nitrux has included Docker for over two years, which aligns with that concept. Indeed, we understand that some users still want to use a package manager but haven’t used a container before; thus, Distrobox makes it easier to get started.

Admittedly, before marching down with torches in anger, let’s make it clear that users can still use a package manager; in fact, users can use any package manager to install new software, just not directly to the root directory anymore; again, we can’t stress this enough.

In today’s tutorial, we will create a container using Distrobox with Podman, install an application, export it, and make the container use hardware acceleration.

Difficulty: ★★☆☆☆

📜 Table of Contents

  1. Containers are not Virtual Machines
  2. About Distrobox
  3. Managing Containers with Distrobox
  4. Accessing a Distrobox Container
  5. Managing Software inside a Distrobox Container
  6. Exporting Applications Installed on a Distrobox Container
  7. Enabling Hardware Acceleration for Applications on Distrobox Container
  8. Using aliases to run software installed on a Distrobox Container from the Host
  9. Running Software from the Host using Libraries from a Distrobox Container
  10. About “rootful” Containers in Distrobox
  11. Troubleshooting
    1. Fix Locale Errors in Containers
    2. Issues with PolicyKit Authentication
    3. Forcefully Stopping a Container

Containers are not Virtual Machines

We understand that containers are a new concept to many people, and we’ve observed that they’re often confused for virtual machines; however, they’re very different. Containers and virtual machines (VMs) are both technologies used to create isolated environments for running applications, but they differ significantly in their architecture and use cases, here’s an overview.

Virtual Machines:

  • Hypervisor: VMs run on a hypervisor, which can be either Type 1 (bare-metal, like VMware ESXi) or Type 2 (hosted, like VirtualBox).
  • Guest OS: Each VM includes a full operating system (guest OS) with virtualized hardware resources (CPU, memory, storage).
    • VMs are generally more resource-intensive because each VM runs a full OS instance, which requires more CPU, memory, and storage.
  • Isolation: VMs provide strong isolation as each VM operates independently with its own OS and resources.
    • Suitable for scenarios where strong isolation is required, such as running different OS types on the same physical hardware.
  • Performance: VMs have higher overhead due to the additional layer of virtualization and the need to run a full OS. This can result in slower performance compared to containers. Overhead from the hypervisor can also add to resource consumption.

Containers:

  • Container Engine: Containers run on a container engine (like Docker or Podman) which uses the host OS’s kernel.
  • Shared OS: Containers share the host OS kernel but have isolated user spaces. This means they do not require a full OS instance for each container.
    • Containers are lightweight as they share the host OS kernel and do not require a full OS instance. This makes them more efficient in terms of resource utilization.
    • Containers can start up quickly and use less memory and storage when compared to VMs.
  • Isolation: Containers provide process-level isolation using namespaces and control groups (cgroups).
    • Containers are frequently used for developing, testing, and deploying applications in a consistent environment.
  • Performance: Containers have lower overhead and can offer near-native performance as they share the host OS kernel.

🔰 Information: For a more in-depth analysis and comparison, see Virtualization and Containerization of Application Infrastructure: A Comparison by Thijs Scheepers (2014).

About Distrobox

Distrobox is based on an OCI image and implements concepts similar to ToolBox, built on top of Podman and OCI standard container technologies. As the project describes, “Simply put it’s a fancy wrapper around podman, docker, or lilipod to create and start containers highly integrated with the hosts.

It has been written in POSIX shell to be as portable as possible and does not have problems with dependencies and the GNU C Library, also known as libc or glibc, version’s compatibility. It also aims to enter the container as fast as possible, every millisecond adds up if you use the container as your default environment for your terminal.

Here are some of the highlights of Distrobox.

  • Provide a mutable environment on an immutable OS, like Endless OS, Fedora Silverblue, OpenSUSE MicroOS, or SteamOS3.
  • Provide a locally privileged environment for sudoless setups (e.g., company-provided laptops, security reasons, etc.)
  • To mix and match a stable base system (e.g., Debian Stable, Ubuntu LTS, RedHat) with a bleeding-edge environment for development or gaming (e.g., Arch, OpenSUSE Tumbleweed, or Fedora with the latest Mesa.)
  • Leverage large, curated distro images for Docker/Podman to manage multiple environments.

Managing Containers with Distrobox

The syntax to create a new container is as follows.

distrobox create -n CONTAINER-NAME -i OS-NAME:VERSION
  • 🔰 Information: To display a complete list of available containers for Distrobox, run the following command.
man distrobox-compatibility

In this example, we’ll create a container using a Debian 12 image for familiarity’s sake. For simplicity, we won’t use the other features available in Distrobox when creating a container.

  • 🔰 Information: The command below pulls the official Debian 12 image from DockerHub and creates a container called “debian-stable-distrobox.”
distrobox create -n debian-stable-distrobox -i debian:stable

We accept to download this container image.

To list containers created with Distrobox, run the following command.

distrobox list

Lastly, to remove containers these must not be in use or running so they must stopped. Once they’re stopped we can remove the containers.

distrobox stop CONTAINER-NAME
distrobox rm CONTAINER-NAME

Finally, to delete the unused container image do the following. First, list the container images, each image will have an ID.

  • 🔰 Information: Distrobox doesn’t have a specific command to do this, so we must use Podman directly.
podman images
podman rmi CONTAINER-IMAGE-ID

Accessing a Distrobox Container

Before entering the container, we must change the root propagation to “shared.”

  • 🔰 Information: Mount propagation allows for sharing volumes mounted by a container to other containers in the same pod or pods on the same node.

We can check this value by running the following command.

findmnt -o PROPAGATION /

If the output reads private,” we cannot enter the container. To change this value, run the following command.

sudo mount --make-rshared /

To access the newly created container, run the following command. Distrobox will do a basic setup and as mentioned before it’s possible to use additional features in Distrobox to include packages, environment variables, drivers (NVIDIA), and even an init.

distrobox enter -n debian-stable-distrobox
  • 🔰 Information: Notice that the hostname has changed in the terminal to that of the container. We can continue using the container or type “exit” to quit the container.
  • ⚠️ Important: Since Distrobox version 1.4.0, the login shell of the container is the same as the default user shell. To change the shell in the container use the command “chsh”.

Even inside the container, we can browse our home directory (and any directory our user can access). However, we can’t browse the root directory of the host since we’d be browsing the container’s root.

Managing Software inside a Distrobox Container

Using Distrobox is unnecessary to enter the container to manage software; we can run the commands directly from the host. The syntax is the following.

distrobox enter -n CONTAINER-NAME -- COMMAND

For example, we can update the package index and install software just like we’d do it in a conventional distribution, in this case, Debian. It’s important to note that actions that require elevated privileges require sudo.

distrobox enter -n debian-stable-distrobox -- sudo apt update

After installing our software, we can run it in the same way, let’s do that with Neofetch.

distrobox enter -n debian-stable-distrobox -- neofetch

Likewise, we can remove software from the container. Let’s remove Neofetch without entering the container.

distrobox enter -n debian-stable-distrobox -- sudo apt remove -y neofetch

Of course, every other option in APT/dpkg will work such as upgrade, autoremove, etc.

Exporting Applications Installed on a Distrobox Container

We can export software we’ve installed in a container using Distrobox. Exporting a program with Distrobox will make the specified software available to the host operating system as a native application, integrated into the applications launcher.

To export an application, it is necessary to enter the container since we can’t do this from the host; once inside, we can run the following command.

distrobox-export --app APPLICATION-EXECUTABLE
  • ⚠️ Important: It’s crucial to understand that the “export” option only works when the software utilizes a desktop launcher (.desktop). For software that doesn’t use a desktop launcher (as most CLI-only utilities and tools do), create an alias in the shell configuration file of the host.

In this example, we will install and export Blender to be available in the host. As we did before, we can install software without entering the container.

distrobox enter -n debian-stable-distrobox -- sudo apt install -y --no-install-recommends blender

Then, we run Blender to check it works.

Great, Blender works fine, as we’d expect. So, now we can export the application.

  • 🔰 Information: When exporting the application we must use the application’s executable, this way Distrobox will know the associated desktop launcher. Distrobox will create the desktop launcher in the directory $HOME/.local/share/applications.
distrobox-export -a blender

Once we do that, Blender will be available to launch from our application menu. Notice that the exported application launcher includes the name of the container where it is installed, this will help organize applications and make it easier to remove them when no longer needed.

Likewise, to delete an exported application, run the following command.

distrobox-export -a -d blender

Enabling Hardware Acceleration for Applications on a Distrobox Container

We must perform the steps below to run applications installed in a container with a Distrobox that requires hardware acceleration like Blender. These steps might not be necessary for all software, especially if it doesn’t require hardware acceleration.

⚠️ Important: Instructions below are for the container used as an example for this tutorial and using Nitrux as the host; adapt to your needs if you’re using a different container.

  • MESA drivers (radeon, amdgpu, i945, etcetera). We only need to install the following packages if the container doesn’t already have them.
distrobox enter --name debian-stable-distrobox -- sudo apt install -y --no-install-recommends libegl1-mesa libgl1-mesa-glx libvulkan1 mesa-vulkan-drivers
  • NVIDIA proprietary driver. We need to have matching versions of the kernel and driver on the host and the container; otherwise, we will see an error in the container when attempting to build the driver. Nitrux uses the Liquorix kernel, to install this kernel in the container run the following commands.
distrobox enter --name debian-stable-distrobox -- sudo wget -P /usr/bin https://liquorix.net/install-liquorix.sh
distrobox enter --name debian-stable-distrobox -- sudo chmod +x /usr/bin/install-liquorix.sh
distrobox enter --name debian-stable-distrobox -- sudo bash /usr/bin/install-liquorix.sh
distrobox enter --name debian-stable-distrobox -- sudo rm /usr/bin/install-liquorix.sh
  • 🔰 Information: For convenience, we created a script that will always install the latest NVIDIA proprietary driver.
distrobox enter --name debian-stable-distrobox -- sudo wget -P /usr/bin https://raw.githubusercontent.com/Nitrux/storage/master/Other/install-nvidia-driver-installer
distrobox enter --name debian-stable-distrobox -- sudo bash /usr/bin/install-nvidia-driver-installer
distrobox enter --name debian-stable-distrobox -- sudo rm /usr/bin/install-nvidia-driver-installer

Using aliases to run software installed on a Distrobox Container from the Host

As we’ve seen, running software from Distrobox is super easy, but let’s say you don’t want to type all that text whenever you want to run something. We can solve that quickly by creating an alias in the shell configuration file ($HOME/.zshrc). We can create an alias for anything we want, for example, if we only want to type “apt” instead of the full Distrobox command “distrobox enter –name debian-stable-distrobox — sudo apt“, we can create an alias, to do this run the following command.

  • ⚠️ Important: Please notice a space at the end, next to “aptin our alias. Adding the space allows the alias to take our input, otherwise, it would simply run the command “apt” as-is.
echo -e "\n# Alias for APT\nalias apt='distrobox enter -n debian-stable-distrobox -- sudo apt '\n" >> ~/.zshrc && source ~/.zshrc

After doing so and after sourcing the file our new alias works. You will also notice that after adding this alias, we do not have to prepend APT with sudo; we run apt [option], for example, apt update instead of sudo apt update because we already use sudo in the alias, and if we were to prepend sudo what we’d be doing is to run “sudo distrobox-enter …”, which is not the objective.

  • ⚠️ Important: Please notice that, when entering the container, if the alias is still active and we type “apt” doing this will inevitably loop into trying to run the container inside the container which will not work. Remove the alias or use a different name before entering the container.

Of course, you can do this for any other software, in any container you create.

Running Software from the Host using Libraries from a Distrobox Container

By using aliases, we have a lot of flexibility; An interesting use case is creating “runtimes.” We can create an alias named “dbox-run” to run any binaries in the host but use the libraries of the container instead of those available in the host, or as a shorthand to run the software we’ve installed on the container. For example, we can do the following to run Neofetch, which is a CLI utility that wouldn’t have a desktop launcher and therefore can’t be exported by default.

First, we add the alias and source the shell configuration file, to do this run the following command.

echo -e "\n# Alias for dbox-run\nalias dbox-run='distrobox enter -n debian-stable-distrobox --'\n" >> ~/.zshrc && source ~/.zshrc

And we can start using our new command.

dbox-run neofetch

Or, as mentioned, we can run binaries from the host, like this binary of Qt Creator (installed manually and downloaded from its official site at https://www.qt.io/download). In this example, if we were to install Qt Creator in the host and run it, it would be impossible for Qt Creator to find the many development headers and libraries it needs to compile projects.

# Running Qt Creator like this won't allow us to build projects

~/Qt/Tools/QtCreator/bin/qtcreator

However, if we run the binary on a container where we have installed the packages it needs, it can build the projects.

#   Running Qt Creator like this will allow us to build projects (after installing the necessary packages on the container like qt5-default, qttools5-dev, cmake, and so on)

dbox-run ~/Qt/Tools/QtCreator/bin/qtcreator

Another use case is running old binaries that do not work with newer libraries; for example, it would be in the case of unmaintained AppImages built against older versions of the GNU C Library (or other libraries included in the AppImage) that do not work with the newer versions that we include in Nitrux (primarily because of deprecated/undefined symbols or functions in newer versions of such libraries).

  • 🔰 Information: It’s worth remembering that while AppImages are self-contained, whatever libraries or binaries its creator did not include in the AppImage are going to load from the root directory of the distribution where the AppImage is running; problems will occur if these libraries and binaries are incompatible; typically, the application will crash with a segmentation fault, or in the case of the AppImage of the example below, an illegal hardware instruction.

For example, this AppImage of Opera (available from AppImageHub and thus listed in the NX Software Center) does not work if we try to run it in Nitrux; it will error out.

Let’s run this unmaintained AppImage using the container we created in this tutorial. It will work once we install the missing libraries in the container because the AppImage’s libraries and binaries were compiled against versions of libraries, like the GNU C Library, compatible with those in the container. We’re using the container’s libraries instead of the newer libraries from the host system, Nitrux.

We could call this container a “runtime,” similar to a “runtime” for other packaging formats like Flatpak or Snaps. To get AppImages to work when running them using a container FUSE must be installed.

  • 🔰 Information: The packages below will allow us to run this particular AppImage using the container we created. We can use our aliases or the complete command sequence, it doesn’t matter.
distrobox enter -n debian-stable-distrobox -- sudo apt install -y --no-install-recommends libfuse2 fuse3 libxtst6 libatk-bridge2.0-0 libgtk-3-0

Then, run the AppImage; let’s assume it’s in our Downloads directory.

dbox-run ~/Descargas/Opera-x86_64.AppImage

We could then create a desktop launcher, put it in $HOME/.local/share/applications, so it’s available in the applications menu, and have it run the command above to execute the AppImage using our newfound “runtime.”

About “rootful” Containers in Distrobox

Our tutorial to use Distrobox does not cover the use of root containers because of what the developer describes here.

⚠️ […] if you use docker, or you use podman with the –root/-r flag, the containers will run as root, so root inside the rootful container can modify system stuff outside the container […]

Future versions of Distrobox will include a sandbox feature, as discussed in their bug tracker. There are instances where a root container may be necessary, such as when accessing devices, i.e., USB devices, internal storage devices, etc., or otherwise accessing specific hardware features, for example, to use a hypervisor that uses libvirt within a container.

  • ⚠️ Important: Use root containers at your own risk!

Troubleshooting

⚠️ Important: Instructions below are for the container used as an example for this tutorial and using Nitrux as the host; adapt to your needs if you’re using a different container.

Fix Locale Errors in Containers

While it doesn’t affect the container’s functionality, in this Debian container’s case, do the following to eliminate those Perl warning messages. Only select the appropriate locale and that’s it, no more errors.

  • ⚠️ Important: These messages appear because the host’s locale differs from the container’s. This issue is not a bug in Nitrux or caused by Nitrux.
distrobox enter -n debian-stable-distrobox -- sudo apt install -y --no-install-recommends locales
distrobox enter -n debian-stable-distrobox -- sudo dpkg-reconfigure locales

Issues with PolicyKit Authentication

Software that uses PolicyKit for authentication will not work out of the box due to issues with containers and DBus. This is a known issue with Distrobox, as noted in this comment by the developer; this is not a problem caused by Nitrux, introduced by Nitrux, or only affecting Nitrux. However, it is possible to alleviate this problem by doing the following.

distrobox enter -n debian-stable-distrobox -- sudo mkdir /run/dbus
distrobox enter -n debian-stable-distrobox -- sudo ln -s /run/host/run/dbus/system_bus_socket /run/dbus/system_bus_socket

After doing this, to run software that would otherwise use “pkexec” we must use “sudo -E“. For example, If we don’t use sudo, Synaptic will complain that it runs without elevated privileges and can’t make changes; if we run it with sudo, it will install the selected package.

Forcefully Stopping a Container

Do the following to stop a container created using Podman (the default in Distrobox).

podman container kill -a

That’s it; this concludes today’s tutorial.