Index
- Part 1: Introduction
- Part 2: Basic configuration files
- Part 3: Creating an unprivileged container on Slackware
- Part 4: Scripts overview
- Part 5: Natting example
- Browse the scripts' folder
- Changelog
A common use of the LXC containers is to isolate services like sql
, ftp
, httpd
, mail etc. in an host server where the only user who will ever login is root
. In this case, handling the unprivileged containers can be quite annoying.
In fact, one would like to have all the containers' filesystems inside the same directory, tipically /lxc, while LXC
will install them in the $HOME/.local/share/lxc directory of the container's owner user. In addition, root
has to administer a container as its owner user (i.e. using sudo -u <user>
), by defining the configuration file and other parameters by means of a long command to type and remember. If you have many unprivileged containers and have to perform tasks like start/stop/attach frequently, your patience will come to an end very quickly.
This is the reason why at a certain point I started to write my own wrapper scripts for the most common LXC
commands. Nothing special, but it seems that no one has published any tools to simplify the LXC
common tasks with unprivileged containers, so it may be worth posting here what I have done.
Let's start with some examples.
Running lxc-ls
as root
shows all the unprivileged containers as stopped even when they are running:
root@host:~# lxc-ls --fancy NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 STOPPED 1 - - - true c2 STOPPED 1 - - - true c3 STOPPED 0 - - - true c4 STOPPED 1 - - - true
An output like this would be more convenient:
root@host:~# lxl # which is my lxc-ls wrapper that I'll show later on Unprivileged running containers of user user1 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 RUNNING 1 - 10.0.0.1 - false Unprivileged running containers of user user2 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c2 RUNNING 1 - 10.0.0.2 - false Unprivileged running containers of user user3 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c3 RUNNING 1 - 10.0.0.3 - false c4 RUNNING 0 - 10.0.0.4 - false c5 RUNNING 1 - 10.0.0.5 - false
Let's consider a few more LXC
commands. Obviously lxc-start
aborts the containers' startup sequence due to id mapping issues if you try to start an unprivileged container as root
:
root@host:~# lxc-start -n c1 lxc-start: c1: lxccontainer.c: wait_on_daemonized_start: 867 Received container state "ABORTING" instead of "RUNNING" lxc-start: c1: tools/lxc_start.c: main: 306 The container failed to start lxc-start: c1: tools/lxc_start.c: main: 309 To get more details, run the container in foreground mode lxc-start: c1: tools/lxc_start.c: main: 311 Additional information can be obtained by setting the --logfile and --logpriority options
Also, you may have to type long commands like this to attach to a container in the proper way
root@host:~# sudo -u user1 lxc-attach \ -n c1 \ --keep-env \ --set-var HOSTNAME=c1.domain \ --set-var USER=root \ --set-var HOME=/root \ -- /bin/bash --rcfile /etc/profile
What if you can do it with a simple command apparently with no need to become the owner of that container? For example
root@host:~# lxu c1 # container c1 UP (container is started, its owner determined dinamically) root@host:~# lxa c1 # attaching container c1 (your env variables and /etc/profile will be passed) root@c1:/root# # inside the container c1 root@c1:/root# exit # exiting from the container c1 root@host:~# # back to the host prompt again root@host:~# lxd c1 # container c1 DOWN
Let's see an example where the creation of a container is made simple. This is how I create a Slackware
15.0 container owned by the user user1
(unprivileged), and with an ip address 10.0.0.22. I want to use my personal list of packages (SLACKPKG_TEMPLATE
) and also a personal LXC
template (LXC_TEMPLATE
) to perform this task:
SLACKPKG_TEMPLATE=my_15.0_template \ LXC_TEMPLATE=my_lxc_template \ RELEASE=15.0 \ my_lxc-create -n <container_name> -i 10.0.0.22 -u user1
or simply
my_lxc-create -n <container_name> -i 10.0.0.22 -u user1
if you set your defaults parameters inside the script. Of course, if you're not a Slackware
user, you can load the LXC
template for your distro and use this same script.
Creating a container owned by root
is even simpler. It will be sufficient not to specify any user (-u
):
my_lxc-create -n <container_name> -i 10.0.0.22
...and so on for other common LXC
commands like lxc-console
, lxc-destroy
, lxc-copy
etc.
I'll show also below how to install all of your containers (unprivileged included!) in the same directory, say /lxc, rather than installing each one in the owner's home directory.
Which distro?
My wrapper scripts will work both for privileged containers (owned by root itself) and unprivileged containers. I wrote them for my Slackware
linux distro, but I think that they can be useful for any other Linux flavors, as they can be easily adapted.
This is the configuration where I tested my scripts:
Slackware Linux 15.0
LXC 4.0.11
libcgroup 0.41
Credits
If you are a Slackware
user and you are looking for unprivileged containers documentation, you should start by reading the Christoph Willing's guide. Thanks to him I migrated from Linux-VServer
, which is no longer maintained. The Cristoph Willing's guide explains in detail how to use libcgroup
to run unprivileged containers and it's the starting point on this topic. In the following I will assume that you are already familiar with the creation and configuration of unprivileged containers. In fact, my installation is mostly an automation of the tasks explained in that guide.
Also the Stéphane Graber's articles are a suitable reading at the beginning.
A special credit is addressed to Matteo Bernardini (Ponce) for his great support to the Slackware
community, not only concerning LXC
.