Linux containers

Linux containers (LXC) is the Linux implementation of FreeBSD Jails.

This page mostly covers usage in debian, however, due to limitations there it's best to adapt this to ubuntu instead. Only minor differences exist and they are not mentioned.

Within a Linux container we can run a self-contained installation of Linux which will utilise the system's kernel.

This is more lightweight method of virtualisation than than offered by Xen, for example.

Install

apt-get install lxc debootstrap bridge-utils
echo "cgroup /sys/fs/cgroup cgroup defaults 0 0" >> /etc/fstab
mount -a

Networking

Simple

/etc/network/interfaces:

auto eth0
iface eth0 inet manual

auto lxcbr0
iface lxcbr0 inet static
 bridge_ports eth0
 address 10.10.44.10
 netmask 255.255.255.0
 gateway 10.10.44.1

Subnet

/etc/network/interfaces:

auto lxcbr0
iface lxcbr0 inet static
 pre-up brctl addbr lxcbr0
 address 10.10.10.1
 netmask 255.255.255.0
 post-down brctl delbr lxcbr0

iptables:

#!/bin/sh
PATH=/sbin

iptables -t filter -F
iptables -t filter -X
iptables -t raw -F
iptables -t nat -F
/usr/sbin/conntrack -F

# raw:PREROUTING
iptables -t raw -A PREROUTING -i lo -j NOTRACK

# raw:OUTPUT
iptables -t raw -A OUTPUT -o lo -j NOTRACK

# filter:INPUT
iptables -t filter -P INPUT ACCEPT

# filter:FORWARD
iptables -t filter -P FORWARD ACCEPT

# filter:OUTPUT
iptables -t filter -P OUTPUT ACCEPT

# nat:POSTROUTING
iptables -t nat -A POSTROUTING -o eth0 -s 10.10.10.0/24 -d 0/0 -j MASQUERADE

sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sysctl -w net.bridge.bridge-nf-call-iptables=0
sysctl -w net.bridge.bridge-nf-call-arptables=0
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.all.proxy_arp=1
sysctl -w net.netfilter.nf_conntrack_max=524288
sysctl -w net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=7440
echo 65536 > /sys/module/nf_conntrack/parameters/hashsize
echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range

exit 0

Initialise

lxc-create -n HOSTNAME -t debian -- -r wheezy -a amd64

Configure

/var/lib/lxc/HOSTNAME/config:

# Template used to create this container: /usr/share/lxc/templates/lxc-debian
# Parameters passed to the template: -r wheezy -a amd64
# For additional config options, please look at lxc.container.conf(5)
lxc.rootfs = /var/lib/lxc/HOSTNAME/rootfs

# Common configuration
lxc.include = /usr/share/lxc/config/debian.common.conf

# Container specific configuration
lxc.mount = /var/lib/lxc/HOSTNAME/fstab
lxc.utsname = HOSTNAME
lxc.arch = amd64

# Network
lxc.network.type = veth
lxc.network.flags = up

# that's the interface defined above in host's interfaces file
lxc.network.link = lxcbr0

# name of network device inside the container,
# defaults to eth0, you could choose a name freely
lxc.network.name = lxcnet0 

lxc.network.hwaddr = 00:FF:AA:00:00:01
lxc.network.veth.pair = veth1

# the ip may be set to 0.0.0.0/24 or skip this line
# if you like to use a dhcp client inside the container
lxc.network.ipv4 = 10.10.10.10/24

# define a gateway to have access to the internet
lxc.network.ipv4.gateway = 10.10.10.1

# Autostart
lxc.start.auto = 1
lxc.start.delay = 5
lxc.start.order = 100

Run

lxc-start -d -n HOSTNAME

Stop

lxc-stop -n HOSTNAME

Unprivileged containers

Root can run containers with lower privileges. First we set aside some user ids to map to the container then configure it.

This has been tested to work Ubuntu vivid. It failed to operate on Debian at this time due to set up of /dev within the container and possibly other issues.

When assigning a range of ids to the root user. Choose what is available, here i chose 200000 because this was free.

usermod --add-subuids 200000-265535 root
usermod --add-subgids 200000-265535 root

The host configuration now needs to map the ids in its config.

lxc.id_map = u 0 200000 65536
lxc.id_map = g 0 200000 65536

The container root will be system uid 200000, and nobody in the container will be 265534, for example..

Before starting, the lcx directory needs the execute permission.

chmod +x /var/lib/lxc

Now we can start and stop the container, attach to it, etc.

Container init: sysvinit & runit

After testing various init and supervisor schemes, the simplest and most efficient solution found was sysvinit in combination with runit.

Also, anything other than sysvinit as init is problematic with lxc, which has trouble stopping the container otherwise (Eg. runit-init).

After some simple set up we expect a process state such as this:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  10660  1736 ?        Ss   01:28   0:00 init [3]  
root      1341  0.0  0.0    196    28 ?        Ss   01:28   0:00 runsvdir -P /etc/service log: ... ...
root      1344  0.0  0.0    172     4 ?        Ss   01:28   0:00 runsv sshd
root      1345  0.0  0.1  49944  5000 ?        S    01:28   0:00 /usr/sbin/sshd -D -e

If you don't require ssh and expect to only use lxc-attach then omit it. If it is installed then it must be disabled in sysvinit.

update-rc.d ssh disable

Ssh will then be run and supervised by runit.

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information