If you are generally used to creating LXC containers using the LXC command toolkit such as lxc-create, lxc-ls etc., you might wonder if it is possible to manually prepare a container image and start it?  The answer is yes and here is how to do it using libvirt tool.

What is libvirt ?

Libvirt is a virtualization driver used to manage KVM and LXC.  The libvirt LXC driver doesn’t depend on the LXC userspace tools but directly deals with the kernel features such as cgroups, namespaces etc. to build the container environment.

Build a rootfs tarball first:

A container image has no magic sauce in it.  It is just a plain rootfs tarball.  If you know how to build a rootfs, you could create your own customized container.  Please refer to this previous article on “Building Rootfs From Scratch”.

Download the libvirt tool:

Download and install the libvirt binary from http://www.libvirt.org/downloads.html.  Alternatively you could install it from your distribution repo.


$ yum install libvirt

Creating a container configuration file:

Next step is to create a container configuration file in XML.  This file would specify the arch type, memory, devices, network interfaces, rootfs filesystem for the container to be started.

Here is a sample LXC configuration file in XML.


$cat test.xml
<domain type='lxc'>
  <name>test</name>
  <memory>500000</memory>
  <os>
    <type>exe</type>
    <init>/bin/sh</init>
  </os>
  <vcpu>1</vcpu>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/lib/libvirt/libvirt_lxc</emulator>
    <filesystem type='mount'>
      <source dir='/tmp/tmp.IaDc7m7ymH’/>
      <target dir='/'/>
    </filesystem>
    <interface type='network'>
      <source network='default'/>
    </interface>
    <console type='pty' />
  </devices>
</domain>
 

Now using the “virsh” command interface of the libvirt tool, create a test container as shown below.


$ virsh -c lxc:/// create test.xml
Domain test created from test.xml
$ virsh -c lxc:/// list --all
Id    Name                           State
----------------------------------------------------
36238 test                           running

Now login to the container from the host shell.

$ virsh -c lxc:/// console test
Connected to domain test
Escape character is ^]
/ #
/ # ls
bin      lib      media    proc     sbin     usr
dev      lib64    mnt      root     sys      var
etc      linuxrc  opt      run      tmp
/ # ls
bin      lib      media    proc     sbin     usr
dev      lib64    mnt      root     sys      var
etc      linuxrc  opt      run      tmp
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 52:54:00:C5:5D:07
inet6 addr: fe80::5054:ff:fec5:5d07/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:41 errors:0 dropped:2 overruns:0 frame:0
TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5960 (5.8 KiB)  TX bytes:906 (906.0 B) 

lo        Link encap:Local Loopback
inet addr:127.0.0.1  Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING  MTU:65536  Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
/ #

If you want to exit from the container and go back to host shell, press ^] inside the container shell.

/# ^]
$
$ virsh -c lxc:/// list --all
Id    Name                           State
----------------------------------------------------
36238 test                           running

You could request libvirt to dump the XML configuration of an active LXC domain to verify its running configuration and assigned values.


$ virsh -c lxc:/// dumpxml test
<domain type='lxc' id='36238'>
  <name>test</name>
  <uuid>5e6ceeea-4055-4ea4-99e6-640dffd9ae60</uuid>
  <memory unit='KiB'>500000</memory>
  <currentMemory unit='KiB'>500000</currentMemory>
  <vcpu placement='static'>1</vcpu>
  <resource>
    <partition>/machine</partition>
  </resource>
  <os>
    <type arch='x86_64'>exe</type>
    <init>/bin/sh</init>
  </os>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/lib/libvirt/libvirt_lxc</emulator>
    <filesystem type='mount' accessmode='passthrough'>
      <source dir='/tmp/tmp.IaDc7m7ymH'/>
      <target dir='/'/>
    </filesystem>
    <interface type='network'>
      <mac address='52:54:00:ce:c7:39'/>
      <source network='default'/>
      <target dev='vnet0'/>
    </interface>
    <console type='pty' tty='/dev/pts/26'>
      <source path='/dev/pts/26'/>
      <target type='lxc' port='0'/>
      <alias name='console0'/>
    </console>
  </devices>
  <seclabel type='none'/>
</domain>
 

The container can be suspended, if required and could be made to run again.

$ virsh -c lxc:/// suspend test
Domain test suspended
$ virsh -c lxc:/// list --all
Id    Name                           State
----------------------------------------------------
36238 test                           paused
$ virsh -c lxc:/// destroy test
Domain test destroyed
$ virsh -c lxc:/// list --all
Id    Name                           State
----------------------------------------------------
$