Setup Linux Container with LXC on Ubuntu 16.04

Linux Container with LXC on Ubuntu 16.04
Linux Container with LXC on Ubuntu 16.04

Linux containers (LXC), is an open source, lightweight operating system-level virtualization software that helps us to run a multiple isolated Linux systems (containers) on a single Linux host. LXC provides a Linux environment as close as to a standard Linux installation but without the need for the separate kernel. LXC is not a replacement of standard virtualization software’s such as VMware, VirtualBox, and KVM, but it is good enough to provide an isolated environment that has its own CPU, memory, block I/O, network.

LXC is released under GNU LGPLv2.1+ license. LXC project is sponsored by Canonical Ltd, who is behind Ubuntu OS.

In this guide, I will show you how to install LXC on Ubuntu 16.04, and create and manage LXC using the command line as well as using LXC Web Portal.

This tutorial should also work on previous versions of Ubuntu, such as Ubuntu 14.04 / 14.10 / 15.04 / 15.10


LXC containers use bridge networking to have access to/from an external network, before starting the container we must create a network bridge on Ubuntu.

Follow the steps to configure bridging on Ubuntu; I am creating bridged interface “br0” using ethernet card “ens33

$ sudo nano /etc/network/interfaces

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

##Bridge  Name ###
auto br0
### Bridge Information
iface br0 inet static
bridge_ports ens33
bridge_stp off
bridge_fd 9
### Bridge IP ###

Install LXC on Ubuntu 16.04:

Now, it’s the time to install LXC. Install the LXC and other packages for the containers to work properly.

$ sudo apt-get install lxc lxc-templates wget bridge-utils

Issue the following command to check everything is okay to run containers.

$ sudo lxc-checkconfig
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-4.4.0-15-generic
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
Bridges: enabled
Advanced netfilter: enabled
FUSE (for use with lxcfs): enabled

--- Checkpoint/Restore ---
checkpoint restore: enabled
File capabilities: enabled

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

Configuring LXC Network:

Disable the default bridge “lxcbr0“,  got created as part of LXC installation.

$ sudo nano /etc/default/lxc-net

Set “USE_LXC_BRIDGE” to “false“.


Configure LXC to use the bridge “br0“, that we created earlier. If you already have any other bridge configured, you can set that in the below file.

$ sudo nano /etc/lxc/default.conf = veth = br0  # Replace with your bridge name = up = 00:16:3e:xx:xx:xx
Reboot the server in order to enable the Network Bridge

Creating First Linux Container:

LXC provides you the ready-made templates for easy installation of Linux containers. Templates are usually found in /usr/share/lxc/templates .

$ sudo ls /usr/share/lxc/templates/

lxc-alpine    lxc-archlinux  lxc-centos  lxc-debian    lxc-fedora  lxc-openmandriva  lxc-oracle  lxc-slackware   lxc-sshd    lxc-ubuntu-cloud
lxc-altlinux  lxc-busybox    lxc-cirros  lxc-download  lxc-gentoo  lxc-opensuse      lxc-plamo   lxc-sparclinux  lxc-ubuntu

Let’s create our first Ubuntu container, issue the following command in terminal

$ sudo lxc-create -n ubuntu_lxc -t ubuntu


-n <container name>

-t <template>

LXC will start creating the container “ubuntu_lxc“, you would get output something like below.

Sample output:

Checking cache download in /var/cache/lxc/xenial/rootfs-amd64 ...
Installing packages in template: ssh,vim,language-pack-en
Downloading ubuntu xenial minimal ...
I: Retrieving InRelease
I: Checking Release signature
I: Valid Release signature (key id 790BC7277767219C42C86F933B4FE6ACC0B21F32)
I: Retrieving Packages
I: Validating Packages
I: Retrieving Packages
I: Validating Packages
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
 Download complete
Copy /var/cache/lxc/xenial/rootfs-amd64 to /var/lib/lxc/ubuntu_lxc/rootfs ...
Copying rootfs to /var/lib/lxc/ubuntu_lxc/rootfs ...
Generating locales (this might take a while)...
  en_IN.UTF-8... done
Generation complete.
Creating SSH2 RSA key; this may take some time ...
2048 SHA256:2gY+KoAVdyeFbKZSjueMtV5pxuMNvPIltXCazRYSpJA [email protected][email protected][email protected]  (RSA)
Creating SSH2 DSA key; this may take some time ...
1024 SHA256:+pXVAkgv7kUDs2iNf7AKbyHMe58OIopJFtnfwJ1fpK0 [email protected][email protected][email protected]  (DSA)
Creating SSH2 ECDSA key; this may take some time ...
256 SHA256:vh1u7wgeMPMeZTWvidZT34FTsQ+oQUKBpJzazjp1Khc [email protected][email protected][email protected]  (ECDSA)
Creating SSH2 ED25519 key; this may take some time ...
256 SHA256:qZvWvYnmJusDZhq5IJ/r8UsWBkrSHUg2vWCevMJgFZk [email protected][email protected][email protected]  (ED25519)
invoke-rc.d: policy-rc.d denied execution of start.

Current default time zone: 'Etc/UTC'
Local time is now:      Thu Apr  7 17:53:19 UTC 2016.
Universal Time is now:  Thu Apr  7 17:53:19 UTC 2016.

# The default user is 'ubuntu' with password 'ubuntu'!
# Use the 'sudo' command to run tasks as root in the container.

Please make a note of login details, you would require this information to log in to the containers.

If you want to create a container based on Ubuntu 14.04, use the following command.

$ sudo lxc-create  -t ubuntu -n trusty_lxc -- -r trusty -a amd64

-r <release>

-a <arc>

Starting Linux Containers:

Once after creating the containers, start it using the following command, -d to run containers in the background.

$ sudo lxc-start -n ubuntu_lxc -d

Now, take a console of the container using the following command.

$ sudo lxc-console -n ubuntu_lxc

Enter the username (ubuntu) and password (ubuntu) to log in. You can find the default credential at the end of the output during the creation of a container.

Sample output:

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Ubuntu Xenial Xerus (development branch) ubuntu_lxc pts/0

ubuntu_lxc login: ubuntu
Welcome to Ubuntu Xenial Xerus (development branch) (GNU/Linux 4.4.0-15-generic x86_64)

 * Documentation:

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

[email protected]_lxc:~$

You can perform all your work in this container as like you do on a Linux servers.

To exit from the container’s console, press “Ctrl+a” followed by “q”. Now, you will be returned to host computer’s terminal.

If you want to connect to the console of the container again ( the container is still running), run the following command.

$ sudo lxc-console -n ubuntu_lxc

Working with Linux Containers:

To listing down the available containers on the host machine, use the following command.

$ sudo lxc-ls


Use the following command to list down the containers that are currently running on the host computer.

$ sudo lxc-ls --active


You could see the same output for both of the commands as I have only one container which is currently running.

You can use the following command to list the containers with detailed information.

$ sudo lxc-ls  -f

ubuntu_lxc RUNNING 0         - -

To get the details of the running container, issue the following command.

$ sudo lxc-info -n ubuntu_lxc

Name:           ubuntu_lxc
State:          RUNNING
PID:            2933
CPU use:        0.90 seconds
BlkIO use:      20.96 MiB
Memory use:     31.67 MiB
KMem use:       0 bytes
Link:           vethFLQOYF
 TX bytes:      3.21 KiB
 RX bytes:      6.41 KiB
 Total bytes:   9.62 KiB

You can use IP address to connect to the containers.

You can stop running containers using “lxc-stop” command, use the following command to stop “ubuntu_lxc”.

$ sudo lxc-stop -n ubuntu_lxc

Cloning containers:

LXC offers a feature of cloning a container from the existing container, run the following command to clone an existing “ubuntu_lxc” container to a new container “ubuntu_lxc_clone”.

Note: You must stop a container before initiating the clone.

$ sudo lxc-copy -n ubuntu_lxc -N ubuntu_lxc_clone

Check out whether a container is created successfully.

$ sudo lxc-ls
ubuntu_lxc       ubuntu_lxc_clone

You can start the cloned container and start working on it.

$ sudo lxc-start -n ubuntu_lxc_clone
$ sudo lxc-console -n ubuntu_lxc_clone

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Ubuntu Xenial Xerus (development branch) ubuntu_lxc_clone pts/0

ubuntu_lxc_clone login: ubuntu
Last login: Sat Apr  9 16:15:22 UTC 2016 from on pts/4
Welcome to Ubuntu Xenial Xerus (development branch) (GNU/Linux 4.4.0-15-generic x86_64)

 * Documentation:
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

[email protected]_lxc_clone:~$

Power off the container from LXC console.

[email protected]_lxc_clone:~$ sudo poweroff

Taking a Snapshot:

LXC also offers an another feature called the snapshot, follow the below steps to perform the snapshot.

Note: Before taking a snapshot, make sure the container is not running. Stop a running container using the following command.

$ sudo lxc-stop -n ubuntu_lxc_clone

For a demo, let’s take a snapshot of ubuntu_lxc_clone.

$ sudo lxc-snapshot -n ubuntu_lxc_clone

Sample output:

lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3371 Snapshot of directory-backed container requested.
lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3372 Making a copy-clone.  If you do want snapshots, then
lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3373 please create an aufs or overlayfs clone first, snapshot that
lxc-snapshot: lxccontainer.c: do_lxcapi_snapshot: 3374 and keep the original container pristine.

To know where the snapshot is being saved, run the following command.

$ sudo lxc-snapshot -L -n ubuntu_lxc_clone
snap0 (/var/lib/lxc/ubuntu_lxc_clone/snaps) 2016:04:09 22:35:16

In Ubuntu, LXC snapshots are stored in “/var/lib/lxc/<containername>/snaps

Restoring Snapshot:

To restore a container from the snapshot, we took earlier, use the following command.

$ sudo lxc-snapshot -r snap0 -n ubuntu_lxc_clone

Destroying Containers:

To remove a container, use the following command.

Note: You must remove the snapshots before destroying the containers. ($ sudo lxc-snapshot -d snap0  -n ubuntu_lxc_clone)

$ sudo lxc-destroy -n ubuntu_lxc_clone

Running a CentOS Container on Ubuntu 16.04:

Install “yum” package for Redhat based containers.

$ sudo apt-get install yum

Create a CentOS 7 container using the following command.

$ sudo lxc-create -n centos_lxc -t centos -- -R 7 -a x86_64

Host CPE ID from /etc/os-release:
Checking cache download in /var/cache/lxc/centos/x86_64/7/rootfs ...
Downloading centos minimal ...
base                                                                                                                                             | 3.6 kB     00:00
base/primary_db                                                                                                                                  | 5.3 MB     12:26
updates                                                                                                                                          | 3.4 kB     00:00
updates/primary_db                                                                                                                               | 3.9 MB     02:17
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package chkconfig.x86_64 0:1.3.61-5.el7 will be installed

Fixing rpmdb location ...
Download complete.
Copy /var/cache/lxc/centos/x86_64/7/rootfs to /var/lib/lxc/centos_lxc/rootfs ...
Copying rootfs to /var/lib/lxc/centos_lxc/rootfs ...
sed: can't read /var/lib/lxc/centos_lxc/rootfs/etc/init/tty.conf: No such file or directory
Storing root password in '/var/lib/lxc/centos_lxc/tmp_root_pass'
Expiring password for user root.
passwd: Success
sed: can't read /var/lib/lxc/centos_lxc/rootfs/etc/rc.sysinit: No such file or directory
sed: can't read /var/lib/lxc/centos_lxc/rootfs/etc/rc.d/rc.sysinit: No such file or directory

Container rootfs and config have been created.
Edit the config file to check/enable networking setup.

The temporary root password is stored in:


The root password is set up as expired and will require it to be changed
at first login, which you should do as soon as possible.  If you lose the
root password or wish to change it without starting the container, you
can change it from the host by running the following command (which will
also reset the expired flag):

        chroot /var/lib/lxc/centos_lxc/rootfs passwd

You can get the default credentials at the end of the output.

Start and take a console of Ubuntu container with the following command. You must change the root password at first login.

$ sudo lxc-start -n centos_lxc -d
$ sudo lxc-console -n centos_lxc

Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

CentOS Linux 7 (Core)
Kernel 4.4.0-15-generic on an x86_64

centos_lxc login: root
You are required to change your password immediately (root enforced)
Changing password for root.
(current) UNIX password:
New password:
Retype new password:
[[email protected]_lxc ~]#

That’s All! thanks for reading. Be social, share this with your friends.


Share This Post

  • great tutorial, thank you. What about port forwarding? How do you setup a specific domain/subdomain or a port to request a specific lxc-container?

    For example
    domain a – ubuntu 16 lamp stack
    domain b – centos lemp stack

    Any tutorial on that?

    Thank you

  • on ubuntu 16.04 when trying to start the lxc-container I get

    lxc-start: tools/lxc_start.c: main: 360 The container failed to start.
    lxc-start: tools/lxc_start.c: main: 362 To get more details, run the container in foreground mode.
    lxc-start: tools/lxc_start.c: main: 364 Additional information can be obtained by setting the –logfile and –logpriority options.

    And this is th elog file:

    lxc-start 20161224223722.297 ERROR lxc_apparmor – lsm/apparmor.c:apparmor_process_label_set:234 – No such file or directory – failed to change apparmor profile to lxc-container-default-cgns
    lxc-start 20161224223722.297 ERROR lxc_sync – sync.c:__sync_wait:57 – An error occurred in another process (expected sequence number 5)
    lxc-start 20161224223722.297 ERROR lxc_start – start.c:__lxc_start:1338 – Failed to spawn container “ubi12_lxc”.
    lxc-start 20161224223727.805 ERROR lxc_start_ui – tools/lxc_start.c:main:360 – The container failed to start.
    lxc-start 20161224223727.805 ERROR lxc_start_ui – tools/lxc_start.c:main:362 – To get more details, run the container in foreground mode.
    lxc-start 20161224223727.805 ERROR lxc_start_ui – tools/lxc_start.c:main:364 – Additional information can be obtained by setting the –logfile and –logpriority options.

    It seems it’s a apparmor bug… ?

  • jbombs16

    when creating the bridge, my network connection goes down. I cannot ssh to the server or when physically at the server, I am unable to go to the internet. Any help? The only way I can get internet back is to remove the bridge.

    • After creating the bridge and modified the LXC config file, reboot the server.

      • jbombs16

        Thanks. I got it to work by having the bridge be dhcp, and just having the router assign the static IP

  • jbombs16

    can anyone give some guidance on sharing an outside directory inside the container?

    I have made several attempts at mounting the directory using the command “lxc config device add”…

    Nothing is working, but I am not sure if I have the syntax correct. Any help?