Installing and configuring LXC for Linux Containers


#### note see “man lxc.conf” for more/different options etc

apt-get install lxc bridge-utils debootstrap 1)

Configure your network as a bridge (in /etc/network/interfaces) so that the future container's veth virtual ethernet interface can share the network link on the physical interface of the host (eth0). More complex setups may be needed (for instance, see /VlanNetworking, for a VLAN + bridge setup description), YMMV.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp

Add the bridge interface and set the eth0 to manual.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
        bridge_ports eth0
        bridge_fd 0

First of all, LXC uses the cgroup kernel facility for resource management. The according file system isn't mounted by default, and LXC doesn't care for where it is mounted, it just needs to be. It seems like /sys/fs/cgroup seems to be the proper place (see 601757), so add the line

"cgroup /sys/fs/cgroup cgroup defaults 0 0"

to your /etc/fstab file and sudo mount cgroup it.

Firewalling works in lxc, but you'll need to load the modules in the host:

echo iptable_mangle >> /etc/modules
echo iptable_nat >> /etc/modules

One final thing before we can go on is checking the the environment via lxc-checkconfig:

#> lxc-checkconfig
Kernel config /proc/config.gz not found, looking in other places...
Found kernel config file /boot/config-2.6.32-5-amd64
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup namespace: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: missing
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
File capabilities: enabled

Note : Before booting a new kernel, you can check its configuration usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

All should be enabled, besides the memory controller, which is sad, but expected. Read more in F.A.Q. about this.

Creating a Debian GNU/Linux 6.0 container

The lxc package ships with a few different template scripts. The templates are located in /usr/lib/lxc/templates, the Debian one is named lxc-debian. The template can be used to install a Debian GNU/Linux 5.0 container. Since Lenny is no longer the current stable release, you'll want to update the template so that it leaves you with a Debian GNU/Linux 6.0 container. Start by copying the template.

cp -a /usr/lib/lxc/templates/lxc-debian /usr/lib/lxc/templates/lxc-debian-squeeze

Apply the patch beneath using the following commands.

patch /usr/lib/lxc/templates/lxc-debian-squeeze /path/to/patch
--- lxc-debian	2010-08-04 19:27:58.000000000 +0200
+++ lxc-debian-squeeze	2011-09-15 09:28:39.123239062 +0200
@@ -90,7 +90,7 @@
@@ -110,7 +110,7 @@
     echo "Downloading debian minimal ..."
     debootstrap --verbose --variant=minbase --arch=$arch \
 	--include $packages \
-	lenny $cache/partial-$arch
+	squeeze $cache/partial-$arch
     if [ $? -ne 0 ]; then
 	echo "Failed to download the rootfs, aborting."
 	return 1
@@ -136,7 +136,7 @@
-    cache="/var/cache/lxc/debian"
+    cache="/var/cache/lxc/debian-squeeze"
     mkdir -p /var/lock/subsys/
@@ -220,7 +220,7 @@
-    cache="/var/cache/lxc/debian"
+    cache="/var/cache/lxc/debian-squeeze"
     if [ ! -e $cache ]; then
 	exit 0

Now that we have a template that will create a Debian GNU/Linux 6.0 container, we can continue creating our container. I used the name vm0 in my example, but you're free to choose a more suitable name.

mkdir -p /var/lib/lxc/vm0
<del>/usr/lib/lxc/templates/lxc-debian-squeeze -p /var/lib/lxc/vm0</del>
lxc-create -t debian-squeeze -n vm0

The template script does not create any of the /dev/tty's, and they need to be created by hand. Use the following instructions.

cd /var/lib/lxc/vm0
mknod -m 666 rootfs/dev/tty1 c 4 1
mknod -m 666 rootfs/dev/tty2 c 4 2
mknod -m 666 rootfs/dev/tty3 c 4 3
mknod -m 666 rootfs/dev/tty4 c 4 4
  • Remove any clock setting/saving from your runlevels (they will likely fail anyways)
  • Remove any starting of udevd as it will not work properly inside a container.
  • Remove any thing from your runlevels that uses /proc/mounts to determine what needs to be unmounted.
  • Remove any thing that tries to remount / as read only (or add mount -o rw,remount / to the rc.sysinit replacement script)

Configuring the Debian GNU/Linux 6.0 container

The configuration file for the container we've just created, is located at /var/lib/lxc/vm0/config. LXC populates it for us, but there are some options that must be added in order for the container to work in our setup. Below are the options I added, not all are required. You can see the manpage for lxc.conf to have an overview of all available options.

lxc.utsname = vm0
# The hostname of the container = veth
# There are a couple of network types you can choose from, but since we are
# using a bridged setup, we must choose veth. = up
# Says the network to be up at start. = br0
# Specifies the network bridge to which the virtual interface will be added. = eth0
# This is the name within the container! Don’t mistake this with the name
# showing up in the host machine! Don’t set it and it will be eth0 anyway..
# =
# Network address assigned to the virtual interface (when NOT using veth). You can provide multiple,
# one per line (man lxc.conf). You have to edit /etc/network/interfaces within
# the container (/var/lib/lxc/vm0/rootfs/etc/network/interfaces) as well! = veth0
# The name of the interface that shows up on the host machine. LXC will come up
# with a name of it's own, but I think this makes more sense. = some-mac
# The MAC-address of the LXC, if you don't specify one, you'll get a new one each time.
# You can leave this off the first time and just grab the MAC-address from the LXC ifconfig-output and put that in the config-file.

Running the Debian GNU/Linux 6.0 container

You can start the container using the following command.

lxc-start -n vm0 -d

The -d options tells it to start in the background.

That should have done the trick. You can check whether it is running with this:

lxc-info -n vm0
'vm0' is RUNNING

Now login to the container, use the lxc console:

lxc-console -n vm0

You should get a login prompt. Just type in “root”, no password (good time to set one).

Thats all. Your first container is up an running. To stop it, just do this:

lxc-stop -n vm0

And check again

#> lxc-info -n vm0
'vm0' is STOPPED

Some other tips for a new installation of Debian, run these two commands:

# dpkg-reconfigure locales
# dpkg-reconfigure tzdata

Removing the container

lxc-destroy -n vm0
rm -rf /var/lib/lxc/vm0/rootfs

Starting the container on boot

uncomment RUN=yes in /etc/default/lxc set CONTAINERS=“” to the names you want to start…. vm0 then create a symlink to /var/lib/lxc/vm0/config in /etc/lxc/vm0.conf

you can start lxc by issuing /etc/init.d/lxc start

Well, thats it for now… you might want to check out to read more about resource handling, but it's outside the scope of this document.

bridge-utils is only needed if you configure a bridged network setup