Welcome to the “Container technologies in Fedora” series! This is the first article in a series of articles that will explain how you can use the various container technologies available in Fedora. This first article will deal with
What is a container?
A container is a user-space instance which can be used to run a program or an operating system in isolation from the system hosting the container (called the host system). The idea is very similar to a
or a virtual machine. The processes running in a container are managed by the same kernel as the host operating system, but they are isolated from the host file system, and from the other processes.
What is systemd-nspawn?
The systemd project considers container technologies as something that should fundamentally be part of the desktop and that should integrate with the rest of the user’s systems. To this end, systemd provides
, a tool which is able to create containers using various Linux technologies. It also provides some container management tools.
In many ways,
is similar to
, but is much more powerful. It virtualizes the file system, process tree, and inter-process communication of the guest system. Much of its appeal lies in the fact that it provides a number of tools, such as
, for managing containers. Containers run by
will integrate with the systemd components running on the host system. As an example, journal entries can be logged from a container in the host system’s journal.
In Fedora 24,
has been split out from the systemd package, so you’ll need to install the
package. As usual, you can do that with a
Creating the container
Creating a container with
is easy. Let’s say you have an application made for Debian, and it doesn’t run well anywhere else. That’s not a problem, we can make a container! To set up a container with the latest version of Debian (at this point in time, Jessie), you need to pick a directory to set up your system in. I’ll be using
Once the directory has been created, you need to run
, which you can install from the Fedora repositories. For Debian Jessie, you run the following command to initialize a Debian file system.
$ debootstrap --arch=amd64 stable ~/DebianJessie
This assumes your architecture is x86_64. If it isn’t, you must change
to the name of your architecture. You can find your machine’s architecture with
Once your root directory is set up, you will start your container with the following command.
$ systemd-nspawn -bD ~/DebianJessie
You’ll be up and running within seconds. You’ll notice something as soon as you try to log in: you can’t use any accounts on your system. This is because
virtualizes users. The fix is simple: remove
from the previous command. You’ll boot directly to the root shell in the container. From there, you can just use
to set a password for root, or you can use
to add a new user. As soon as you’re done with that, go ahead and put the
flag back. You’ll boot to the familiar login console and you log in with the credentials you set.
All of this applies for any distribution you would want to run in the container, but you need to create the system using the correct package manager. For Fedora, you would use DNF instead of
. To set up a minimal Fedora system, you can run the following command, replacing the absolute path with wherever you want the container to be.
$ sudo dnf --releasever=24 --installroot=/absolute/path/ install systemd passwd dnf fedora-release
Setting up the network
You’ll notice an issue if you attempt to start a service that binds to a port currently in use on your host system. Your container is using the same network interface. Luckily,
provides several ways to achieve separate networking from the host machine.
The first method uses the
flag, which only creates a loopback device by default. This is ideal for environments where you don’t need networking, such as build systems and other continuous integration systems.
Multiple networking interfaces
If you have multiple network devices, you can give one to the container with the
flag. To give
to my container, I would add the flag
. While an interface is assigned to a container, the host can’t use it at the same time. When the container is completely shut down, it will be available to the host again.
Sharing network interfaces
For those of us who don’t have spare network devices, there are other options for providing access to the container. One of those is the
flag. This forwards a port on the container to the host. The format is
, where protocol is either
is a valid port number on the host, and
is a valid port on the container. You can omit the protocol and specify only
. I often use something similar to
You can enable complete, host-only networking with the
flag, which creates a virtual Ethernet interface between the host and the container. You can also bridge two connections with
Using systemd components
If the system in your container has D-Bus, you can use systemd’s provided utilities to control and monitor your container. Debian doesn’t include
in the base install. If you want to use it with Debian Jessie, you’ll want to run
To easily manage containers, systemd provides the
, you can log in to a container with
, check the status with
, reboot with
, or power it off with
Other systemd commands
Most systemd commands, such as
, support containers with the
option. For example, if you want to see the journals of a container named “foobar”, you can use
. You can also see the status of a service running in this container with
Working with SELinux
If you’re running with SELinux enforcing (the default in Fedora), you’ll need to set the SELinux context for your container. To do that, you need to run the following two commands on the host system.
$ semanage fcontext -a -t svirt_sandbox_file_t "/path/to/container(/.*)?" $ restorecon -R /path/to/container/
Make sure you replace “/path/to/container” with the path to your container. For my container, “DebianJessie”, I would run the following:
$ semanage fcontext -a -t svirt_sandbox_file_t "/home/johnmh/DebianJessie(/.*)?" $ restorecon -R /home/johnmh/DebianJessie/