In Part 1 of this Unprivileged containers in Slackware article, we discussed how to arrange the system requirements to run unprivileged containers in Slackware. Please ensure the steps in Part 1 have been done before proceeding with anything you find here! In this second part we'll go through the steps to construct and run an unprivileged container in Slackware after which, in Part 3 of this series, we describe a method to provide networking for the container.
Much of the information here on this page is based on Stephane
Graber's Introduction
to unprivileged containers, one of a series of his excellent
blog posts about LXC. Although we'll be concentrating here on how
to make unprivileged containers work in the Slackware environment,
reading Stephane's introduction first is highly recommended.
Having thoroughly read Stephane's post, you'll be aware that some
problems remain when generating an unprivileged container directly
with lxc-create. At the moment, when lxc-create is
run as an ordinary user, the only valid template is the download
template which downloads a premade container suitable for running
in unprivileged mode.
There are now two distinct methods we can use to create an unprivileged container, the classic and the modern.
In the classic method, our strategy is to first create an ordinary root privileged container and then convert it to an unprivileged container. Such a container could then itself be made the target for the download template but we won't bother with that here - we'll just create, then run an unprivileged container. The steps involved using the classic method are:
Step 0 - Check your environment
Before going through these steps in detail, be aware that all
steps from Part 1 must
have been set up correctly. Ensure that when you run:
lscgroup
it shows the newly configured control group qwerty (or
whatever it was named).
Now the steps for creating an unprivileged container using the classic method:
Step 1 - Create standard root privileged container
As root, or using sudo, create a standard container with some
name, say test1, with the following command:
sudo MIRROR=http://slackware.osuosl.org
lxc-create -n test1 -t slackware
This creates a container at /var/lib/lxc/test1 using the
template at /usr/share/lxc/templates/lxc-slackware (from
Slackware's lxc package). The container will be a minimal
version of Slackware -current. Note that it will be owned by root
and resides in a root owned part of the file system; we need to
change that. You could run the container now (sudo lxc-start -n
test1) before proceeding, just to verify its all OK, but
that is not generally necessary unless you noticed strange output
in the creation process.
Step 2 - Remap uids & gids
The aim of this step is to change all the owner and group ids in
the container to the subuid and subgid of the user. Recall that in
Part 1, we created the /etc/subuid and /etc/subgid
files containing a line something like chris:100000:65536.
We therefore want to change all the all uid=0 files in the
container to be uid=100000, all uid=1 to be uid=100001, etc. (up
to a limit of 65536). Rather than doing this by hand we use the uidmapshift
tool which is driven by the container-userns-convert
script, available from Serge Hallyn's nsexec
files. From there, download container-userns-convert
and uidmapshift.c, then compile uidmapshift with:
gcc -o uidmapshift uidmapshift.c
Near the end of the container-userns-convert , around
line 61, change the call to uidmapshift to be ./uidmapshift,
then make container-userns-convert executable. We're now
ready to do the conversion; run:
sudo ./container-userns-convert test1
100000
which should quite quickly finish and, if successful, output:
Container test1 has been converted
Step 3 - Move container to user's filespace
Just as /var/lib/lxc is the default top directory for
ordinary containers, the default location for unprivileged user
containers is the $HOME/.local/share/lxc directory -
if it doesn't exist, create it with:
mkdir -p $HOME/.local/share/lxc
and ensure that each directory from $HOME to
$HOME/.local/share/lxc have execute bits set e.g. chmod a+x
$HOME.
Now copy or move the entire container into the user's file space:
sudo cp -a /var/lib/lxc/test1
$HOME/.local/share/lxc/
and allow the user to edit the container and its config file with:
sudo chown chris:users
$HOME/.local/share/lxc/test1 $HOME/.local/share/lxc/test1/config
then:
sudo chmod a+rx $HOME/.local/share/lxc/test1
Edit the config file to change any references to the container's
original location, converting them to the new location e.g.
change:
lxc.rootfs = /var/lib/lxc/test1rootfs
to:
lxc.rootfs =
/home/chris/.local/share/lxc/test1/rootfs
and change:
lxc.mount = /var/lib/lxc/test1/rootfs/etc/fstab
to:
lxc.mount =
/home/chris/.local/share/lxc/test1/rootfs/etc/fstab
Also, if it isn't there already, add the line:
lxc.mount.auto = proc:mixed sys:ro cgroup
to the config file; then remove the proc and sysfs entries in /home/chris/.local/share/lxc/test1/rootfs/etc/fstab
The need for this may change in future versions of the Slackware
template.
Before running the new unprivileged container, it is advisable to disable its klogd facility (else expect 100% cpu utilisation). Disable klogd by editing the file /home/chris/.local/share/lxc/test1/rootfs/etc/rc.d/rc.syslog, commenting out the call to /usr/sbin/klogd -c 3 -x at around line 22.
Step 4 - Run the unprivileged container
The unprivileged container should now start by running (as the ordinary
user) the command:
lxc-start -n test1
(later, lxc-start -n test1 -d may be more convenient but
for now, in case of problems, its good to see the output of the
container booting up). To then log in to the running container,
run, in another terminal:
lxc-console -n test1
or:
lxc-attach -n test1
Potential Problems
Next step: Part 3 - Networking unprivileged containers
Having attached or logged into the new container, you may have
noticed its minimal collection of software and already thought
about how to install more. This will involve downloading software
from a remote repository, for which networking of some sort will
be needed. The next article,
Part 3 - Running unprivileged containers,
will describe how to achieve that.
Contact
Please send any questions, comments, advice etc., to Chris
Willing <chris.willing _at_ linux.com>