LXC

On this page 7

LXC, short for Linux Containers, is a user-space toolset and library that creates system containers: isolated Linux environments that run their own init system, services and users while sharing the host kernel. In Linux virtualization, LXC sits between a plain chroot and a full virtual machine, offering near-native performance with an experience that resembles a lightweight server.

LXC does not emulate hardware. It combines kernel features, mainly namespaces, cgroups, capabilities, seccomp and mandatory access control profiles, into a coherent container runtime. Tools such as Incus, LXD and Proxmox VE build management layers on top of the same foundation.

How LXC builds a system container

Starting an LXC container means asking the kernel to create a process inside a new set of namespaces. That process becomes PID 1 of the container, usually systemd or another init system, and it sees its own process table, hostname, network interfaces, mount tree and user IDs.

Resource limits come from cgroups, which cap CPU, memory, I/O and the number of processes for the whole container. Security boundaries are reinforced by dropping capabilities, applying a seccomp filter and loading an AppArmor or SELinux profile. The root file system is normally a directory, a ZFS or Btrfs subvolume, or an LVM volume on the host.

The table maps each building block to the isolation it provides.

FeatureWhat it isolates or limitsContainer effect
PID namespaceProcess IDsContainer sees only its own processes
Mount namespaceFile system treeOwn root file system and mounts
Network namespaceInterfaces, routes, firewallOwn IP stack, often through a veth pair
User namespaceUser and group IDsRoot inside maps to unprivileged host ID
CgroupsCPU, memory, I/O, task countEnforced resource limits
Seccomp and MAC profileSystem calls and resource accessReduced kernel attack surface
Kernel features used by LXC

Privileged and unprivileged containers

The most important security decision in LXC is whether a container is privileged or unprivileged. The difference lies in the user namespace mapping of the container’s root account.

PropertyPrivileged containerUnprivileged container
Root UID mappingContainer root is host UID 0Container root maps to a high host UID
Escape impactAttacker may gain host rootAttacker lands as an unprivileged user
Device and mount accessBroadRestricted
Configuration effortSimplerNeeds subuid and subgid ranges
Recommended useTrusted legacy workloads onlyDefault for most deployments
Privileged and unprivileged LXC containers

Unprivileged containers use ranges from /etc/subuid and /etc/subgid, typically 65,536 IDs per container. Files created by container root therefore belong to an ID such as 100000 on the host, which is why sharing host directories with containers requires careful ID mapping.

LXC compared with virtual machines and application containers

LXC is often confused with both virtual machines and application container platforms. The comparison below places it among the neighboring Terms of Linux virtualization, such as KVM, QEMU and libvirt.

ApproachKernelTypical workloadOverhead
LXC system containerShared with hostFull Linux system with initVery low
Application containerShared with hostOne process per imageVery low
KVM with QEMUOwn guest kernelAny operating systemLow to moderate
WSL 2Own Linux kernel in a lightweight VMLinux tools on WindowsLow
LXC and related virtualization approaches

Because LXC shares the kernel, it cannot run Windows or a different kernel version, and kernel modules must be loaded on the host. In exchange, containers start in about a second, use memory only for their processes, and reach near-native disk and network throughput without paravirtual drivers such as Virtio.

Libvirt can manage LXC through its own driver, but most administrators use the native lxc-* commands or a higher-level manager. Application container tools follow a different philosophy: immutable images and one service per container, while LXC containers are usually long-lived and administered like small servers.

Working with LXC

The classic LXC toolset consists of lxc-prefixed commands and a configuration file per container, usually at /var/lib/lxc/NAME/config. The table lists the core commands.

CommandPurpose
lxc-create -t downloadCreate a container from a distribution image
lxc-start / lxc-stopStart or cleanly stop a container
lxc-attachRun a command or shell inside a container
lxc-ls –fancyList containers with state and addresses
lxc-snapshotCreate or restore snapshots
lxc-copyClone a container
Core LXC commands

Configuration keys such as lxc.cgroup2.memory.max, lxc.net.0.type = veth and lxc.idmap define limits, networking and ID mapping. Networking usually connects a veth interface to a host bridge, which makes each container appear as a separate machine on the network.

Limitations and common mistakes

LXC provides strong practical isolation, but its boundary is weaker than a hypervisor boundary because every container talks to the same kernel. The following points summarize the issues seen most often.

  • A kernel vulnerability affects all containers on the host, so prompt host kernel updates are essential.
  • Privileged containers for untrusted users effectively give those users a path to host root.
  • Nested containers and FUSE mounts require explicit configuration and often relaxed security settings.
  • Tools that read /proc directly may report host totals for memory and CPU unless LXCFS is used.
  • Bind-mounted host directories show unexpected ownership when ID mapping is not planned.

The idea in brief

Picture a large apartment building. Every apartment has its own door, rooms and residents, but all of them share the same foundation, plumbing and electricity. LXC builds apartments like that on a single Linux computer.

Each container feels like a separate small server, with its own programs and users. Because they share the building’s foundation, the Linux kernel, they start almost instantly and waste very little memory. The trade-off is that a crack in the foundation would affect every apartment.

A practical scenario

A university department runs one physical server with 32 cores and 128 GB of memory and must give twelve student project teams their own Linux servers for a semester. Full virtual machines would reserve memory for twelve guest kernels and take longer to provision.

The administrator creates twelve unprivileged LXC containers from a Debian image, each with lxc.cgroup2.memory.max set to 8G and a CPU weight that shares cores fairly. Each container receives an address on a bridged network and its own SSH access.

Provisioning all twelve takes a few minutes, idle containers use little memory, and snapshots before risky changes let teams recover from mistakes in seconds. At the end of the semester, the containers are archived and destroyed.