A Brief Introduction to Linux Containers with LXC

In this post, I’m going to provide a brief introduction to working with Linux containers via LXC. Linux containers are getting a fair amount of attention these days (perhaps due to Docker, which leverages LXC on the back-end) as a lightweight alternative to full machine virtualization such as that provided by “traditional” hypervisors like KVM, Xen, or ESXi.

Both full machine virtualization and containers have their advantages and disadvantages. Full machine virtualization offers greater isolation at the cost of greater overhead, as each virtual machine runs its own full kernel and operating system instance. Containers, on the other hand, generally offer less isolation but lower overhead through sharing certain portions of the host kernel and operating system instance. In my opinion full machine virtualization and containers are complementary; each offers certain advantages that might be useful in specific situations.

Now that you have a rough idea of what containers are, let’s take a closer look at using containers with LXC. I’m using Ubuntu 12.04.3 LTS for my testing; if you’re using something different, keep in mind that certain commands may differ from what I show you here.

Installing LXC is pretty straightforward, at least on Ubuntu. To install LXC, simply use apt-get:

apt-get install lxc

Once you have LXC installed, your next step is creating a container. To create a container, you’ll use the lxc-create command and supply the name of the container template as well as the name you want to assign to the new container:

lxc-create -t <template> -n <container name>

You’ll need Internet access to run this command, as it will download (via your configured repositories) the necessary files to build a container according to the template you specified on the command line. For example, to use the “ubuntu” template and create a new container called “cn–01″, the command would look like this:

lxc-create -t ubuntu -n cn-01

Note that the “ubuntu” template specified in this command has some additional options supported; for example, you can opt to create a container with a different release of Ubuntu (it defaults to the latest LTS) or a different architecture (it defaults to the host’s architecture).

Once you have at least one container created, you can list the containers that exist on your host system:

lxc-list

This will show you all the containers that have been created, grouped according to whether the container is stopped, frozen (paused), or running.

To start a container, use the lxc-start command:

lxc-start -n <container name>

Using the lxc-start command as shown above is fine for initial testing of your container, to ensure that it boots up as you expect. However, you won’t want to run your containers long-term like this, as the container “takes over” your console with this command. Instead, you want the container to run in the background, detached from the console. To do that, you’ll add the “-d” parameter to the command:

lxc-start -d -n <container name>

This launches your container in the background. To attach to the console of the container, you can use the lxc-console command:

lxc-console -n <container name>

To escape out of the container’s console back to the host’s console, use the “Ctrl-a q” key sequence (press Ctrl-a, release, then press q).

You can freeze (pause) a container using the lxc-freeze command:

lxc-freeze -n <container name>

Once frozen, you can unfreeze (resume) a container just as easily with the lxc-unfreeze command:

lxc-unfreeze -n <container name>

You can also make a clone (a copy) of a container:

lxc-clone -o <existing container> -n <new container name>

On Ubuntu, LXC is configured by default to start containers in /var/lib/lxc. Each container will have a directory there. In a container’s directory, that container’s configuration will be stored in a file named config. I’m not going to provide a comprehensive breakdown of the settings available in the container’s configuration (this is a brief introduction), but I will call out a few that are worth noting in my opinion:

  • The lxc.network.type option controls what kind of networking the container will use. The default is “veth”; this uses virtual Ethernet pairs. (If you aren’t familiar with veth pairs, see my post on Linux network namespaces.)
  • The lxc.network.veth.pair configuration option controls the name of the veth interface created in the host. By default, a container sees one side of the veth pair as eth0 (as would be expected), and the host sees the other side as either a random name (default) or whatever you specify here. Personally, I find it useful to rename the host interface so that it’s easier to tell which veth interface goes to which container, but YMMV.
  • lxc.network.link specifies a bridge to which the host side of the veth pair should be attached. If you leave this blank, the host veth interface is unattached.
  • The configuration option lxc.rootfs specifies where the container’s root file system is stored. By default it is /var/lib/lxc/<container name>/rootfs.

There are a great deal of other configuration options, naturally; check out man 5 lxc.conf for more information. You may also find this Ubuntu page on LXC to be helpful; I certainly did.

I’ll have more posts on Linux containers in the future, but this should suffice to at least help you get started. If you have any questions, any suggestions for additional resources other readers should consider, or any feedback on the post, please add your comment below. I’d love to hear from you (courteous comments are always welcome).

Tags: , , , ,

  1. Hein Bloed’s avatar

    For introductional purposes a video from LinuxCon Europe 2013. Containers and the Cloud:

    Nice summary of the current state of affairs in Linux containers.

  2. Fento’s avatar

    I second the LinuxCon Europe 2013 video, the video is very well done. I dismissed containers as a technology until I watched this video.

    Has anyone used containers for load generation? Would this be a valid use case for them?

    Have you heard if anyone is working on:
    Live migration of a single container instance?
    Ways to mitigate the issue where a single container instance can down all the other container instances?

  3. Lennie’s avatar

    @Fento while we are posting YouTube videos I might as well do the same. :-)

    http://criu.org/Main_Page is working on making live migration possible:

    TL;DR Lots of stuff works, with some exceptions.

    By the way, just noticed there are a ridiculous amount of container-related talks on that channel:
    http://www.youtube.com/channel/UCIxsmRWj3-795FMlrsikd3A/search?query=container
    http://www.youtube.com/channel/UCIxsmRWj3-795FMlrsikd3A/search?query=lxc
    http://www.youtube.com/channel/UCIxsmRWj3-795FMlrsikd3A/search?query=openvz
    http://www.youtube.com/channel/UCIxsmRWj3-795FMlrsikd3A/search?query=namespace

  4. Hein Bloed’s avatar

    Live migration is possible and has always been possible with the OpenVZ kernel (because it includes checkpoint/restore, which is now pushed upstream with criu).

    For bigger containers it is advised to use shared storage (and ploop probably).
    Small containers can be live migrated without shared storage easily

  5. Fento’s avatar

    Just saw that Oracle Linux 6.5 was released. It has Linux Containers in it should be interesting.

  6. Darryl Giles’s avatar

    “Full machine visualization offers greater isolation” – Total isolation can be achieved via software, obviously because that is what hypervisors do, but they do not do this through obscurity. No, there are software methods with Linux which will allow LXC developers to implement total isolation between containers if this hasn’t already been achieved. Your opinions are outdated.

  7. slowe’s avatar

    Darryl, your bias is showing. :-) Note that I did not say that full machine virtualization was better (it worse) than Linux containers, only that it offered greater isolation. You are correct that total isolation can be achieved in software–via a “traditional” hypervisor or via an OS-level container. Each approach has it’s advantages and disadvantages, and it’s up to us to determine which approach is the right approach for the task at hand.

  8. Waseem’s avatar

    Verify informative posts about LXC…

    I would like to add my contribution to LXC community:
    LXC API for Java: https://github.com/waseemh/lxc-java

  9. Kay’s avatar

    Why not just use FreeBSD with its jails system ?

  10. slowe’s avatar

    Kay, it may not be possible to switch to FreeBSD (for any number of reasons).

Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>