LXC: Getting started with Linux Containers
If you keep up date, you probably know a great revolution is going on in the whole IT industry: containers. While Docker gets much of the attention, it isn’t the only player in the field. This post is entirely dedicated to LXC: Docker’s older brother.
What are containers?
The first thing to understand is the concept of container. Before starting I suggest you not to read if you’re not comfortable with virtualization. That said containers are similar to Virtual Machines but how are they different? The principal difference is that Virtual Machines are completely abstracted, the full stack starting from BIOS/UEFI up to the kernel is abstracted and different for each VM. Containers on the other side take advantage of the existing architecture and virtualize thereafter. Without the need of abstracting the hardware much less resources are used hence containers are more lightweight than VMs. Containers tend also to share as much as possible with each other (posing security problems) whilst VMs tend to lock the resources and share as less as possible.
LXC and Docker
As I was mentioning earlier Docker is the major player in the container world at the moment, but it isn’t the only one. Linux Containers are even older than Docker, and the Docker project itself has used LXC as base for a while (before switching to libcontainer). So we might say LXC is the older brother of Docker. However related they may be, they fundamentally differ in one thing: the scope. Being container technologies, both Docker and Linux Containers are Operating-System-level virtualization, but:
- Docker specializes in deploying applications.
- LXC tries to be as close as possible to virtual machines reducing the overhead.
While it is common to have a Docker container run a single application, LXC containers are similar to virtual machines and enable you to achieve higher density by reducing the overhead imposed by full-fledged virtual machines. Linux Containers are able to achieve this by taking advantage of Linux Kernel’s cgroups and namespaces.
Before starting let’s sum up the requirements (directly from linuxcontainers.org):
- One of glibc, musl libc, uclib or bionic as your C library
- Linux kernel >= 2.6.32
Extra dependencies for lxc-attach:
- Linux kernel >= 3.8
Extra dependencies for unprivileged containers:
- cgmanager or another CGroup manager configuring your system for unprivileged CGroups operation
- A recent version of shadow including newuidmap and newgidmap
- Linux kernel >= 3.12
Getting started with LXC
The first thing you have to do is install lxc:
For Debian-based distro do:
# apt-get install lxc
# yum install lxc
After you have done that you’re ready to go: let’s download the first template for your first container. In this example I’m calling the container test and I’m specifying I want to download the template list.
$ sudo lxc-create -n test -t download Setting up the GPG keyring Downloading the image index --- DIST RELEASE ARCH VARIANT BUILD --- centos 7 amd64 default 20160524_02:16 debian jessie amd64 default 20160523_04:37 debian jessie arm64 default 20160517_22:42 debian jessie i386 default 20160523_04:37 debian jessie powerpc default 20160523_04:37 fedora 23 amd64 default 20160524_01:27 fedora 23 i386 default 20160524_01:27 gentoo current amd64 default 20160524_14:12 gentoo current i386 default 20160524_14:12 opensuse 13.2 amd64 default 20160524_00:53 ubuntu xenial amd64 default 20160523_04:37 ubuntu xenial i386 default 20160523_04:37 # The output is actually truncated --- Distribution: ubuntu Release: xenial Architecture: amd64 Downloading the image index Downloading the rootfs Downloading the metadata The image cache is now ready Unpacking the rootfs --- You just created an Ubuntu container (release=xenial, arch=amd64, variant=default) To enable sshd, run: apt-get install openssh-server For security reason, container images ship without user accounts and without a root password. Use lxc-attach or chroot directly into the rootfs to set a root password or create user accounts.
This was just to download the template on which the test container will be based. I also selected distribution, release and architecture interactively. Let’s now run it and verify:
$ sudo lxc-start -n test -d $ sudo lxc-info -n test Name: test State: RUNNING PID: 4598 IP: 10.0.3.147 CPU use: 0.16 seconds BlkIO use: 4.00 KiB Memory use: 12.19 MiB KMem use: 0 bytes Link: veth42SDVF TX bytes: 1.27 KiB RX bytes: 3.16 KiB Total bytes: 4.43 KiB
As you can see the container has been started! Let’s now log into it:
$ sudo lxc-attach -n test [email protected]:/# cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04 LTS"
We’re now into the container and much like a virtual machine, we can execute commands and do things that are isolated from other containers. Let’s now delete the container:
[email protected]:/# exit $ sudo lxc-stop -n test $ sudo lxc-destroy -n test Destroyed container test
You’re now aware of LXC, the older brother of Docker and one of the first modern container technologies for Linux. The whole tutorial was based on privileged containers which ran as root and were administered by root. But Linux Containers also supports unprivileged containers that can be run by any user and are more secure. Now that you understand how LXC works you might be interested in learning Docker too.