Containerizing the GUI separates your work and your game.
Virtualization has always been a game for the rich and thrifty
Enthusiasts who can't afford fancy server-class components, often
fight to keep up. Linux offers free high quality hypervisors, but when
When you start throwing real workloads on the host, its resources become
quickly saturated. Free memory was not saved on an old Dell desktop
will fix this situation. When a properly decorated host is off
You may want to consider containers within your reach instead.
Instead of virtualizing an entire computer, containers allow parts of Linux
Kernel can be portioned into several pieces. This happens without that
Effort for emulating hardware or running multiple identical kernels. A full one
A GUI environment like GNOME Shell can be started in a container.
with a little chewing gum.
You can do this through namespaces, a feature built into Linux
Kernel. A closer look at this function would go beyond the scope
Articles, but a quick example shows how these functions can be created
Container. Each type of namespace segments a different part of the kernel.
For example, the PID namespace prevents processes within the namespace
of other processes running in the kernel. As a result, this
Processes believe that they are the only ones that run on the computer. Everyone
The namespace does the same for other areas of the kernel. The
The mount namespace isolates the file system of the processes it contains. The
The network namespace provides a unique network stack for running processes
in them. The IPC, user, UTS, and cgroup namespaces do the same for
these areas of the kernel too. When the seven namespaces are combined,
The result is a container: an environment that is isolated enough to believe that it is
a free-standing Linux system.
Container frameworks abstract the details of configuring namespaces
removed from the user, but each framework has a different focus. Docker is
the most popular and was designed to run multiple copies of identical ones
Scale containers. LXC / LXD should create containers so easily
mimicking certain Linux distributions. Indeed, previous versions of LXC
included a collection of scripts that created popular's file systems
Distributions. A third option is the libvirt lxc driver. Unlike how
it may sound like libvirt-lxc doesn't use LXC / LXD at all. Instead, the
The libvirt-lxc driver handles kernel namespaces directly. libvirt-lxc
can also be integrated into other tools of the libvirt suite, so that the
The configuration of libvirt-lxc containers is similar to that of virtual machines
is executed in other libvirt drivers instead of a native LXC / LXD container. It
is easy to learn, even if the branding is confusing.
I chose libvirt-lxc for this tutorial for several reasons. By doing
First, Docker and LXC / LXD have already published instructions on how to do this
GNOME Shell in a container. I couldn't find a similar one
Documentation for libvirt-lxc. Second, libvirt is the ideal setting for
Run containers alongside traditional virtual machines because both exist
managed with the same tools. Third, configure a container in
libvirt-lxc offers a good lesson in the compromises involved
The biggest decision is whether you run a privileged or a non-privileged one
Container. A privileged container uses and has the user namespace
identical UIDS both on the inside of the container and on the outside. As a
Result: Container applications that are run by a user with administrative functions
Privileges could do significant harm if a security breach allows
break out of the container. For this reason, an unprivileged container is executed
seems like an obvious choice. However, an unprivileged container will not
can access the acceleration functions of the GPU. Depending on
The purpose of the container – such as photo editing – may not be helpful.
There is an argument for only running software that you trust
Container while untrustworthy software for the stronger isolation of a
right virtual machine. Although I think the GNOME desktop is one
I trustworthily show the creation of a non-privileged container
Process can be applied if necessary.
Next, you need to decide if you want to use a remote display protocol.
like spice or VNC, or to let the container render its contents in one of them
the host's virtual terminals. Using a display protocol allows access to
the container from anywhere and increases its isolation. On the other hand,
There is probably no additional risk if the container accesses the host
Hardware as two different processes that run outside of a namespace.
If the software you are running is not trustworthy, use full virtual software
Machine instead. I use the latter option from libvirt-lxc to access the hosts
Hardware in this article.
The last consideration is a little bit smaller. First, libvirt-lxc won't
Split / run / udev / data to the container, which prevents libinput
run in it (it is possible to mount / run, but that causes others
Problems). You must write a short xorg.conf to use the input devices
as a result. The arrangement of the nodes should be under the host
The directory / dev / input is constantly changing, the container configuration and xorg.conf
File must be adjusted accordingly. After all of that is clear, let's do it
Prepare the container host
A basic installation of Fedora 29 Workstation includes libvirt, but a few
additional components are required. The libvirt-lxc driver itself must be
Set up. Let's use the virt manager and
virt-bootstrap tools too
Accelerate the creation of the container. There are also some side effects
Utilities you will need for later. They are not necessary, but they will help
They monitor the resource usage of the container. Refer to your package
Manager documentation, but I did the following:
sudo dnf install libvirt-daemon-driver-lxc virt-manager
Irtvirt-bootstrap virt-top evtest iotop
Note: libvirt-lxc was no longer supported as a container by Red Hat Enterprise Linux
Framework in version 7.1. It is still being developed upstream and
available for installation in the RHEL / Fedora distribution family.
Before you create the container, you must also change it
/etc/systemd/logind.conf to ensure that getty doesn't start on the virtual page
Terminal that you want to transfer to the container. Comment that out
Line and set it to 3 so that it only starts on the first three ttys
Terminals. Set ReserveVT to 3 to reserve the third vt
instead of the sixth. You must restart the computer after making changes
This file. After restarting, check whether getty is only active on ttys 1
to 3. Change these parameters as required. The modified
The lines of my logind.conf file look like this:
AutoVTs = 3
ReserveVT = 3
Prepare the container file system
You can create the container's file system directly from
virt-manager, but a few changes to the command line are still required,
Let's do virt-bootstrap there too.
virt-bootstrap is a great one
libvirt tool that downloads base images from Docker. That gives you a fountain
well-maintained file system for the distribution you want to run in
Container. I found that on Fedora 29 I had to turn off SELinux to get it
virt-bootstrap to run properly. Additional packages must be added
to the Docker base image (like x.org and gnome-shell) and some systemd
Services must be unmasked:
sudo setenforce 0
virt-bootstrap docker: // fedora / path / to / container
sudo dnf –installroot / path / to / container install xorg-x11-server-Xorg
xorg-x11-drv-evdev xorg-x11-drv-fbdev gnome-session-xsession xterm
net-tools iputils dhcp-client passwd sudo
sudo chroot / path / to / container
# unmask the getty and logind services
cd / etc / systemd / service
# Make sure that all files in the container can be accessed
sudo chown -R user: user / path / to / container
sudo setenforce 1
Note: There are several alternative ways to create the operating system file system. Many package managers have options that can be used to create packages
installed in a local directory. In dnf this is the one
Installroot option. in the
apt-get is the option -o Root =. There is also an alternative tool that
works similar to what is called virt-bootstrap
Build the container
When you open virt-manager you will see the lxc hypervisor
is missing. You add
To do this, select File and Add connection in the menu. Select "LXC
(Linux Containers) "from the drop-down list and click Connect.
Then return to the File menu and click New Virtual Machine.
Figure 1. Add the libvirt-lxc driver to virt-manager.
The first step in creating a new virtual machine / container in virt-manager is
to select the hypervisor under which to run.
Select "LXC" and
the option for an operating system container. Click Next.
Figure 2. Make sure you select operating system containers.
virt-bootstrap has already been run, so give virt-manager the location of
the container's file system. Click Next.
Give the container as much CPU and memory as is appropriate for its use.
Just leave the default settings for this container. Click Next.
In the last step, click on "Adjust configuration before installation".
and click Finish.
A window opens in which you can adjust the containers
Construction. With the Overview option selected, expand the area labeled
"User name". Click "Enable User Namespace" and type
65336 in the Number field for user ID and group ID. Then click Apply
Click on "Start installation". virt-manager starts the container. You
However, you are not yet ready to leave. Switch off the container and leave it
The container is activated by activating the user namespace
You have to change the configuration of the container
to share that
Host's devices. In particular the target tty (tty6), the loopback tty
(tty0) require mouse, keyboard and frame buffer (/ dev / fb0) entries
created in the configuration. Quickly identify which items are shown under / dev / input
are the mouse and keyboard by running sudo evtest and pressing ctrl-c after
It listed the devices. From the output I could see that my mouse is open
/ dev / input / event3 and my keyboard is / dev / input / event6.
Figure 4. A list of input devices on my workstation
You cannot simply access the / etc / libvirt folder from the folder
Enter a root bash session by running sudo bash and change the directory to
/ etc / libvirt / lxc. Open the container configuration and scroll down to
the device section. You must add hostdev tags each
Device you just
identified. Use the following layout:
I added the following tags for my container:
It's time to start the container! Open it in virt-manger and click on
Start button. Once a container has the option to use the host's tty,
It is not uncommon for the login prompt to appear only on this tty. In order to
Press Ctrl-Alt-F6 to switch to tty6 and log in to the container. As I
As mentioned above, you need to write an xorg.conf with an input section. To the
Your reference, here is the one I wrote:
AutoAddDevices option False
Device option "/ dev / input / event3"
AutoServerLayout option true
"Device" option "/ dev / input / event6"
AutoServerLayout option true
Don't forget to do the usual management of a new Linux system
requires with the container. Which steps you take depends on the
Distribution that you execute within the container, but at least ensure
You create a separate user, add him to the wheel group and configure the
Network interface of the container. If that's out of the way, run
Start the GNOME shell.
Figure 5. GNOME shell running in the container
After running GNOME, check the container's use of the system
Resources. Tools like top are not container-compatible. To get a real one
Impression of the memory usage of the container, use virt-top
Connect virt-top to the libvirt-lxc driver by running virt-top -c
lxc: /// outside the container. Next, run machinectl to get the internal one
((Email protected) ~) $ machinectl
MACHINE CLASS SERVICE OS VERSION ADDRESSES
Container name container libvirt-lxc – – –
Run machinectl status -l container name to print the
Process of the container
Tree. At the beginning of the command output, note the PID of the
The root process is listed as a leader. To see how much storage the container has
consumed in total, you can pass the leader PID upwards
runs top -p
((Email protected) ~) $ top -p leaderpid
Since: Mon 2018-12-17 22:03:24 EST; 19min ago
Leader: 5017 (systemd)
Service: libvirt-lxc; Class container
Unit: machine-lxc x2d5016 x2dfedora.scope
((Email protected) ~) $ top -p 5017
top – 22:43:11 up 1:11, 1 user, load average: 1.57, 1.26, 0.95
Tasks: 1 in total, 0 running, 1 sleeping, 0 stopped, 0 zombie
% Cpu (s): 1.4 us, 0.3 sy, 0.0 ni, 98.2 id, 0.0 wa, 0.1 hi,
~ 0.0 si, 0.0 st
MiB Mem: 15853.3 total, 11622.5 free, 2363.5 used, 1867.4
↪buff / cache
MiB Swap: 7992.0 total, 7992.0 free, 0.0 used. 12906.4 available Mem
PID USER PR NI VIRT RES SHR S% CPU% MEM TIME + COMMAND
5017 root 20 0 163.9 m 10.5 m 8.5 m S 0.0 0.1 0: 00.22 systemd
The container uses a total of 163 MB of virtual memory – compared to fairly slim
the resources used by a full virtual machine! You can monitor I / O in a
The same applies to sudo iotop -p leaderpid. You can
Calculate the hard disk size of the container
with du -h / path / to / container. My full
The container provided weighed 1.4 GB.
These numbers will obviously increase with additional software and workloads
are given to the container. I want to install a separate environment
Build dependencies, and my most common use for these containers is
Run Gnome Builder. I've also occasionally set up a privileged container to
Run darktable for photo editing. I rarely edit photos enough to do it
doesn't make sense to keep darktable installed outside of a container,
and I find the idea that I could tare the container filesystem and
Recreate it on another computer if I wanted to be reassuring. If you find
You are dependent on cash and have to get the most out of your host.
You might use a container instead of a virtual machine.