LXC is an acronym for Linux Containers. It is nothing but an operating system-level virtualization technology for running multiple isolated Linux distros (systems containers) on a single Linux host. In this tutorial you will learn how to install and manage LXC containers on Ubuntu Linux server.
Say hello to LXC
Fig.01: Linux containers
Traditional virtualization such as KVM/XEN/VMWARE and paravirtualization need a full operating system image for each instance. You can run any operating system using traditional virtualization.
Install the lxc on Ubuntu
Type the following apt-get command to install :
$ sudo apt-get install lxc
Sample outputs:
Fig.02: Installing LXC on Ubuntu
LXC and networking
LXC creates a NATed bridge called lxcbr0 for you. Each container will have one veth NIC and all traffic routed using the lxcbr0 bridge. To view current settings, enter:
$ sudo brctl show
Sample outputs:
bridge name bridge id STP enabled interfaces lxcbr0 8000.fe09977d9e4f no vethH1OXMH
To see an IP address assigned to the lxcbr0, enter:
$ sudo ifconfig lxcbr0
Sample outputs:
lxcbr0 Link encap:Ethernet HWaddr fe:09:97:7d:9e:4f inet addr:10.0.3.1 Bcast:10.0.3.255 Mask:255.255.255.0 inet6 addr: fe80::4820:9fff:fe01:4d52/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:40 errors:0 dropped:0 overruns:0 frame:0 TX packets:42 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3553 (3.5 KB) TX bytes:4383 (4.3 KB)
To see DHCP range used by containers, enter:
$ ps aux | grep lxc-dns | grep -o 'dhcp-range.[0-9].* '
Sample outputs:
dhcp-range 10.0.3.2,10.0.3.254 --dhcp-lease-max=253 --dhcp-no-override --except-interface=lo --interface=lxcbr0 --dhcp-leasefile=/var/lib/misc/dnsmasq.lxcbr0.leases
To check the current kernel for lxc support, enter:
$ lxc-checkconfig
Sample outputs:
Kernel configuration not found at /proc/config.gz; searching... Kernel configuration found at /boot/config-3.13.0-76-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 CONFIG_NF_NAT_IPV4: enabled CONFIG_NF_NAT_IPV6: enabled CONFIG_IP_NF_TARGET_MASQUERADE: enabled CONFIG_IP6_NF_TARGET_MASQUERADE: enabled CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled --- Checkpoint/Restore --- checkpoint restore: enabled CONFIG_FHANDLE: enabled CONFIG_EVENTFD: enabled CONFIG_EPOLL: enabled CONFIG_UNIX_DIAG: enabled CONFIG_INET_DIAG: enabled CONFIG_PACKET_DIAG: enabled CONFIG_NETLINK_DIAG: enabled File capabilities: enabled Note : Before booting a new kernel, you can check its configuration usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig
Creating unprivileged container
Unprivileged containers run the same way as privileged ones, simply without using sudo or root access. This is more secure as you can’t be root on the host even if you managed to escape container. The steps are as follows:
- Create a new user for lxc.
- Set password for for lxc.
- Find out allocated subuids and subgids for the lxc user.
- Create a default container configuration file for lxc user
- Create a new container.
- Start a new container.
- Deploy apps in newly created unprivileged container.
Step – 1: Create a new user for lxc
Type the following command to add a user called mylxcusr:
$ sudo useradd -s /sbin/bash -c 'unprivileged lxc user' -m mylxcusr
Step – 2: Set password for for lxc
Set the password for mylxcusr
$ sudo passwd mylxcusr
Step -3: Find out allocated subuids and subgids for the lxc user
Type the following command
$ sudo grep mylxcusr /etc/sub{gid,uid}
Sample outputs:
/etc/subgid:mylxcusr:100000:65536 /etc/subuid:mylxcusr:100000:65536
Note down the values.
Step – 4:Create a default container configuration file for lxc user
Make sure the user “mylxcusr” is allowed up to 10 veth type devices to be created and added to the bridge called lxcbr0. In other words networking will only work if you add the following lines:
$ sudo vi /etc/lxc/lxc-usernet
Append the following line:
mylxcusr veth lxcbr0 10
Save and close the file. Now switch to new user using su or just login using the ssh client:
$ su - mylxcusr
OR
$ ssh mylxcusr@server1.cyberciti.biz
$ ssh mylxcusr@74.86.144.194
$ id
Sample outputs:
uid=1002(mylxcusr) gid=1002(mylxcusr) groups=1002(mylxcusr)
Once logged into a remote machine, type the following command to create ~/.config/lxc/ director as follows:
$ mkdir -p ~/.config/lxc
Finally, create ~/.config/lxc/default.conf file as follows:
$ cp /etc/lxc/default.conf ~/.config/lxc/default.conf
Edit the file, enter:
$ vi ~/.config/lxc/default.conf
Append the configuration as follows (use mapped user and group id ranges 100000:65536 from step #3):
lxc.id_map = u 0 100000 65536 lxc.id_map = g 0 100000 65536
Step – 5:Create a new container
Let us create a new Ubuntu container called httpd, enter:
$ lxc-create -t download -n httpd -- -d ubuntu -r trusty -a amd64
Sample outputs:
Fig.03: Create an Ubuntu container
Step – 6:Start a new container
To start httpd container type:
$ lxc -n httpd -d
$ echo $?
$ lxc-ls --fancy
NAME STATE IPV4 IPV6 AUTOSTART --------------------------------------------- httpd RUNNING 10.0.3.61 - NO
To start a process inside a running container or just to login, enter:
$ lxc-attach -n httpd
Sample session inside a httpd container:
root@httpd:/# id uid=0(root) gid=0(root) groups=0(root) root@httpd:/# ifconfig eth0 Link encap:Ethernet HWaddr 00:16:3e:ea:ce:fa inet addr:10.0.3.61 Bcast:10.0.3.255 Mask:255.255.255.0 inet6 addr: fe80::216:3eff:feea:cefa/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:37 errors:0 dropped:0 overruns:0 frame:0 TX packets:35 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:3502 (3.5 KB) TX bytes:3362 (3.3 KB)
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)
root@httpd:/# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 14.04.3 LTS Release: 14.04 Codename: trusty
For security reason, container images ship without user accounts and without a root password. Setup a root password for httpd container:
# passwd root
To enable sshd for httpd container, run:
# apt-get install openssh-server
You can login from host to container using ssh:
$ ssh user@10.0.3.255
Step – 7:Deploy apps in newly created unprivileged container
You can now install nginx, php or any other application. Just attach to container and run commands or apps as per your need.
Important management commands
Here is a quick overview of useful commands:
How do I start a container?
$ lxc-start -n {container-name-here} -d
$ lxc-start -n mysql -d
How do I stop a container?
$ lxc-stop -n {container-name-here}
$ lxc-stop -n mysql
How do I destroy (delete) a container?
$ lxc-destroy -n {container-name-here}
$ lxc-destroy -n mysql
How do I list all containers?
$ lxc-ls
$ lxc-ls --fancy
How do I update or patch my container?
Use the lxc-attach command to update your container that is powered by Ubuntu or Debian:
$ lxc-attach -n mysql apt-get -- -qq update
$ lxc-attach -n mysql apt-get -- -qq upgrade
$ lxc-attach -n nginx yum -- -y update
How do I force DHCP to provide a persistent IP address to my container?
As a root on host run the following command:
$ sudo vi /etc/lxc/dnsmasq.conf
To give containers on lxcbr0 a persistent ip address based on domain name, you can add entries as follows:
dhcp-host=httpd,10.0.3.20 dhcp-host=mysql,10.0.3.21 dhcp-host=nginx,10.0.3.23 dhcp-host=php7,10.0.3.24
Save and close the file.
How do I create CentOS/Gentoo/Fedora or any other flavour of LXC?
$ lxc-create -t download -n {container-name-here} -- -d {DISTRONAME} -r {RELEASE} -a {ARCH}
$ lxc-create -t download -n bar -- -d centos -r 6 -a amd64
$ lxc-create -t download -n foo -- -d gentoo -r current -a amd64
$ lxc-create -t download -n db -- -d ubuntu -r precise -a i386
$ lxc-create -t download -n nginx -- -d debian -r jessie -a amd64
$ lxc-create -t download -n mysql -- -d fedora -r 22 -a amd64
$ lxc-create -t download -n maridb -- -d oracle -r 6.5 -a amd64
$ lxc-create -t download -n cahcing -- -d plamo -r 5.x -a amd64
The list of lxc flavour:
--- DIST RELEASE ARCH VARIANT BUILD --- centos 6 amd64 default 20160203_02:16 centos 6 i386 default 20160203_02:16 centos 7 amd64 default 20160203_02:16 debian jessie amd64 default 20160202_22:42 debian jessie armel default 20160111_22:42 debian jessie armhf default 20160111_22:42 debian jessie i386 default 20160202_22:42 debian sid amd64 default 20160202_22:42 debian sid armel default 20160111_22:42 debian sid armhf default 20160111_22:42 debian sid i386 default 20160202_22:42 debian squeeze amd64 default 20160202_22:42 debian squeeze armel default 20150826_22:42 debian squeeze i386 default 20160202_22:42 debian wheezy amd64 default 20160202_22:42 debian wheezy armel default 20160111_22:42 debian wheezy armhf default 20160111_22:42 debian wheezy i386 default 20160202_22:42 fedora 21 amd64 default 20160203_01:27 fedora 21 armhf default 20160112_01:27 fedora 21 i386 default 20160203_01:27 fedora 22 amd64 default 20160203_01:27 fedora 22 armhf default 20160112_01:27 fedora 22 i386 default 20160203_01:27 gentoo current amd64 default 20160203_14:12 gentoo current armhf default 20160111_14:12 gentoo current i386 default 20160203_14:12 oracle 6.5 amd64 default 20160203_11:40 oracle 6.5 i386 default 20160203_11:40 plamo 5.x amd64 default 20160202_21:36 plamo 5.x i386 default 20160202_21:36 ubuntu precise amd64 default 20160203_03:49 ubuntu precise armel default 20160112_03:49 ubuntu precise armhf default 20160203_03:49 ubuntu precise i386 default 20160203_03:49 ubuntu trusty amd64 default 20160203_03:49 ubuntu trusty arm64 default 20150604_03:49 ubuntu trusty armhf default 20160203_03:49 ubuntu trusty i386 default 20160203_03:49 ubuntu trusty ppc64el default 20160201_03:49 ubuntu vivid amd64 default 20160203_03:49 ubuntu vivid arm64 default 20150604_03:49 ubuntu vivid armhf default 20160203_03:49 ubuntu vivid i386 default 20160203_03:49 ubuntu vivid ppc64el default 20160201_03:49 ubuntu wily amd64 default 20160203_03:49 ubuntu wily arm64 default 20150604_03:49 ubuntu wily armhf default 20160203_03:49 ubuntu wily i386 default 20160203_03:49 ubuntu wily ppc64el default 20160201_03:49 ubuntu xenial amd64 default 20160203_03:49 ubuntu xenial armhf default 20160203_03:49 ubuntu xenial i386 default 20160203_03:49 ---
Conclusion
And, there you have it, a container running on Ubuntu Linux 14.04 LTS in unprivileged mode. I suggest you visit the official project home page and Ubuntu lxc wiki page for more information.
🐧 Get the latest tutorials on Linux, Open Source & DevOps via:
- RSS feed or Weekly email newsletter
- Share on Twitter • Facebook • 8 comments... add one ↓
Category | List of Unix and Linux commands |
---|---|
File Management | cat |
Firewall | Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04 |
Network Utilities | dig • host • ip • nmap |
OpenVPN | CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04 |
Package Manager | apk • apt |
Processes Management | bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time |
Searching | grep • whereis • which |
User Information | groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w |
WireGuard VPN | Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04 |
Hi, very nice detailed article. As it is FAQ directory I think it should have one of top questions: “how is it different to docker?”. Docker went mainstream and it is much easier for readers of your article to have a picture of `lxc` from the known docker point of view. Cheers
> Step – 2: Set password for for lxc
> Set the password for mylxcusr
> $ sudo mylxcusr
Maybe:
$ sudo passwd mylxcusr
Thanks for the heads up!
I like LXD better. Though, it’s still in beta, i think.
when I start: lxc -n httpd -d, it tells me: lxc-start: lxc_start.c: main: 344 The container failed to start.
If I sttart the command with the debugging enabled, it tells me: lxc-start 1458080603.878 ERROR lxc_start – start.c:__lxc_start:1213 – failed to spawn ‘httpd’
You may have a process called httpd running already. Use top or ‘ps aux | grep -i httpd’ to verify that httpd does not exits.
Host Debian Stretch 64b
Unprivileged Container – Debian Jessie 64
Unprivileged containers start, stop, attach bla bla bla
However from within container apt-get install fails with
debconf: delaying package configuration, since apt-utils is not installed
dpkg: warning: ‘ldconfig’ not found in PATH or not executable
dpkg: warning: ‘start-stop-daemon’ not found in PATH or not executable
dpkg: error: 2 expected programs not found in PATH or not executable
Note: root’s PATH should usually contain /usr/local/sbin, /usr/sbin and /sbin
E: Sub-process /usr/bin/dpkg returned an error code (2)
lxc-attach –name “container-name” –clear-env helped me get passed those errors and install through apt…