While it looks like that lots of people are moving towards using Docker, sometimes having a complete lightweight virtual machine can be just as useful - Docker is meant to be a per process virtualizer. Although it can be used as a virtual machine, it's discouraged.

I have lots of positive experiences using OpenVZ but it looks like in the more recent versions, it became a full blown Linux distribution and you cannot install just OpenVZ without it's Linux distribution. Also - OpenVZ always required it's own modified Linux kernel to work which sometimes can be a blocker.

LXC is an alternative to OpenVZ which also has been around for a while - it doesn't need a custom kernel, so I figured I would give it a try.

1. Install LXC:

yum -y install epel-release
yum -y install lxc lxc-templates lxc-extra libvirt

2. Enable the libvirtd service:

systemctl enable libvirtd

3. Start the libvirtd service:

systemctl start libvirtd

4. Enable the LXC service:

systemctl enable lxc

5. Start LXC:

systemctl start lxc

6. List the available operating system templates:

ls -alh /usr/share/lxc/templates/

7. Create an Alpine Linux container:

lxc-create --name first --template alpine

8. Check that your container has been created:

lxc-ls -f
NAME STATE IPV4 IPV6 AUTOSTART 
-------------------------------------
first STOPPED - - NO

9. Try to start the container:

lxc-start --name first --daemon

If you get this error:

lxc-start: conf.c: instantiate_veth: 3097 failed to attach 'veth1OBU0W' to the bridge 'virbr0': No such device
lxc-start: conf.c: lxc_create_network: 3389 failed to create netdev
lxc-start: start.c: lxc_spawn: 875 failed to create the network
lxc-start: start.c: __lxc_start: 1149 failed to spawn 'first'
lxc-start: lxc_start.c: main: 341 The container failed to start.
lxc-start: lxc_start.c: main: 345 Additional information can be obtained by setting the --logfile and --logpriority options.

I found the solution here: https://unix.stackexchange.com/a/179868 - it means that you probably did not install libvirtd.

10. Try to connect to the container:

lxc-console --name first

11. Once you connect use "root" for your username - no password is set

12. Setup your network so you can download packages:

ifconfig eth0 192.168.122.2 netmask 255.255.255.0
route add default gw 192.168.122.1

13. Test to see that it worked by pinging www.google.com:

ping www.google.com
PING www.google.com (172.217.6.36): 56 data bytes
64 bytes from 172.217.6.36: seq=0 ttl=57 time=2.987 ms
64 bytes from 172.217.6.36: seq=1 ttl=57 time=3.171 ms

14. Update the package lists and install dhclient:

apk update
apk add dhclient

15. Get a DHCP address by using dhclient:

dhclient eth0

16. Check what IP address you got using ifconfig:

first:~# ifconfig eth0
eth0 Link encap:Ethernet HWaddr FE:DD:58:EA:E9:77 
 inet addr:<span style="color: #ff0000;">192.168.122.95</span> Bcast:192.168.122.255 Mask:255.255.255.0
 inet6 addr: fe80::fcdd:58ff:feea:e977/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:88 errors:0 dropped:0 overruns:0 frame:0
 TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:5517 (5.3 KiB) TX bytes:1865 (1.8 KiB)

17. How is this possible you might ask? We did not do any network configuration on the host. This is possible because the host (libvirtd) automatically started dnsmasq as a dhcp server. Let's take a look by using `virsh net-list` on the host:

[root@centos7lxc dnsmasq.d]# virsh net-list
 Name State Autostart Persistent
----------------------------------------------------------
 default active yes yes

As you can see there's one network called 'default' which is in an 'active' state and set to automatically start.

18. Let's get some more info on this network by using `virsh net-info default`:

[root@centos7lxc dnsmasq.d]# virsh net-info default
Name: default
UUID: 832dae27-f3f3-4293-87e8-f29b34338b62
Active: yes
Persistent: yes
Autostart: yes
Bridge: virbr0

In the above you can also see that the 'default' network is using a virtual bridge called 'virbr0'.

19. Finally you can see that dnsmasq is indeed running:

ps fauxwww | grep -i dnsmasq
root 11578 0.0 0.0 112648 936 pts/6 S+ 10:45 0:00 \_ grep --color=auto -i dnsmasq
nobody 9373 0.0 0.0 15544 832 ? S 10:15 0:00 /sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
root 9374 0.0 0.0 15516 296 ? S 10:15 0:00 \_ /sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper

20. Don't like the default IPs that virsh is using? change them:

virsh net-edit default

In the next post, I'll take a look at how we can set limits for disk space used by a container, memory and CPU.

Sources: