I have been spending a lot of time searching for alternatives to virtual machines. I do love my VMs but I hate the idea of dedicating resources (such as RAM) that never get used. There is memory ballooning but it is a trade off for the usage of other resources. Also I am crazy and obsessive about efficiency. VMs still have their place but we now have a new, awesome tool available to us: LXC.
Install
The LXC team offers us a PPA making this setup super easy. This will also handle future updates for us.
Install the software…
sudo apt-add-repository -y ppa:ubuntu-lxc/stable
sudo apt-get update
sudo apt-get install lxc
Network
Optional
You could skip this step but then you would only be able to access your containers on the same host on which they are run. There is also port forwarding (say, via iptables) but that is overly complicated for anything other than simple TCP/UDP stuff (and boring). We are going to do a bridge so that all containers can access the network and all remote hosts can access the containers as if they were physical machines on the network.
This should have been installed with LXC but just to be safe…
sudo apt-get install bridge-utils
Fire up your favorite text editor and open /etc/network/interfaces
. In it add
auto lxcbr0
iface lxcbr0 inet static
address [primary IP address]
netmask [primary netmask]
gateway [primary gateway]
dns-nameservers [primary DNS server(s)]
bridge_ports [primary network interface]
replacing everything above within and including the brackets.
Next we need to replace all lines for the primary network interface with
iface eth0 inet manual
You may have multiple network segments. Configuring this is left as an exercise for the user.
Unprivileged Containers
We could just start creating containers now. However a potential problem may arise as they will all be run as root
. Theoretically this is fine because you should never be able to break out of a container but bugs happen. So we are not making ourselves more vulnerable than we need to be we will be setting up unprivileged containers to be run as our unprivileged user.
Allow our user account to use the bridge…
echo "$USER veth lxcbr0 1024" | sudo tee -a /etc/lxc/lxc-usernet
Create Upstart script…
In /etc/init/lxc-unprivileged.conf
add…
description "LXC Unprivileged Containers"
author "Mike Bernson <mike@mlb.org>"
start on started lxc
script
USERS="[user]"
for u in $USERS; do
cgm create all lxc$u
cgm chown all lxc$u $(id -u $u) $(id -g $u)
lxc-autostart -L -P /home/$u/.local/share/lxc | while read line;
do
set -- $line
/usr/local/bin/startunprivlxc lxc$u $u $1
sleep $2
done
done
end script
Make sure to replace [user]
with your user account.
Create the container start script…
In /usr/local/bin/startunprivlxc
add…
#!/bin/sh
cgm movepid all $1 $$
sudo -iH -u $2 -- lxc-start -n $3 -d
… and make it executable…
sudo chmod +x /usr/local/bin/startunprivlxc
Create our mappings and settings for our containers to use…
mkdir -p ~/.config/lxc/
echo "lxc.id_map = u 0 100000 65536" > ~/.config/lxc/default.conf
echo "lxc.id_map = g 0 100000 65536" >> ~/.config/lxc/default.conf
echo "lxc.network.type = veth" >> ~/.config/lxc/default.conf
echo "lxc.network.link = lxcbr0" >> ~/.config/lxc/default.conf
Create Contaiers
Here is where the magic happens.
lxc-create --name [name] --template download
Again with the text editor open ~/.local/share/lxc/[name]/config
. In it add
lxc.start.auto = 1
Make sure to replace [name]
with your container name in both commands.
These two steps will allow you to create new, unprivileged containers which autostart on boot running the distribution, release, and architecture of your choice.
Attach to Contaiers
In order to get into the console you only need a single command…
lxc-attach --name [name]
If you like you can use this to install an SSH server (do not forget to setup a new user so you are not logging in as root). You could also just log into the host and lxc-attach
each time. Up to you.
More
There are many more things you can do. For example, create separate networks (say, one for public communications and another for container-to-host-to-container communications) or limit resources so one rouge container does not ruin it for the others and the host itself. A dedup‘ing filesystem (such as ZFS) would also probably get great ratios.
Research, experiment, and play with this very cool bit of engineering.
Sources
https://www.launchpad.net/~ubuntu-lxc/
https://help.ubuntu.com/lts/serverguide/network-configuration.html
https://help.ubuntu.com/lts/serverguide/lxc.html
Thanks
Mike Bernson
https://lists.linuxcontainers.org/pipermail/lxc-users/2015-January/008221.html
https://lists.linuxcontainers.org/pipermail/lxc-users/2015-January/008222.html