Skip to main content

Command Palette

Search for a command to run...

Beyond Docker: Setting Up and Managing Linux Containers with LXC

Updated

Linux Containers, or LXC, is an interface for Linux kernel vritualisation. You can create Linux containers that enable persistence, and system-level functionality. When comparing LXC to Docker, they both serve different use cases. Docker is more suitable for application containerisation whereas LXC is more relevant for system-level functionality and also persistent environments.

Installing LXC

$ sudo apt update
$ sudo apt install -y lxc

Since we need to create an unprivileged container (for security reasons), the user that will be attached to this container needs to have permissions to create network devices.

$ sudo bash -c 'echo <username> veth lxcbr0 10 >> /etc/lxc/lxc-usernet'
$ cat /etc/lxc/lxc-usernet

# USERNAME TYPE BRIDGE COUNT
<username> veth lxcbr0 10

Setting up the config file

The configuration file for lxc may not exist. So create the directory inside the .config directory and copy the default.conf located in /etc/lxc/.

$ mkdir -p ~/.config/lxc
$ cp /etc/lxc/default.conf ~/.config/lxc/default.conf
$ chmod 664 ~/.config/lxc/default.conf

The configuration file has to be updated with the UID and GID of the unprivileged user. They can both be extracted from the /etc/subuid and /etc/subgid files.

$ cat /etc/subuid
ubuntu:100000:65536
<username>:165536:65536

$ cat /etc/subgid
ubuntu:100000:65536
<username>:165536:65536

$ echo lxc.idmap = u 0 165536 65536 >> ~/.config/lxc/default.conf
$ echo lxc.idmap = g 0 165536 65536 >> ~/.config/lxc/default.conf

$ cat ~/.config/lxc/default.conf
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
lxc.idmap = u 0 165536 65536
lxc.idmap = g 0 165536 65536

Setting access control list

To prevent possible permission errors, we need to set up an access control list on our .local directory.

$ sudo apt update
$ sudo apt install -y acl
$ setfacl -R -m u:165536:x ~/.local

This command sets an ACL (Access Control List) for a specific user (UID 165536), recursively on the ~/.local directory, giving that user execute (x) permission.

Creating an unprivileged container

Once the setup is complete, we can create a container using the download template. This gives us all available images designed to work without privileges.

$ lxc-create --template download --name unpriv-cont-user

Once the image index is downloaded, the CLI tool will display the images and await for the user to provide the distro, release and architecture required. In this case, ubuntu, jammy and amd64 will be used.

---

Distribution:
ubuntu
Release:
jammy
Architecture:
amd64

Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created an Ubuntu jammy amd64 (20250404_20:34) container.

Starting the container

Now the container has been created, we can start it.

$ lxc-start -n unpriv-cont-user -d

With the container running we can interact with its environment.

$ lxc-attach -n unpriv-cont-user
# hostname
unpriv-cont-user
# exit
$ lxc-stop -n unpriv-cont-user

More from this blog

Bernie Ops

20 posts