Introduction
While Docker revolutionized application containerization with its lightweight, application-focused containers, LXC (Linux Containers) takes a different approach by providing system-level containers that run complete Linux distributions. LXC and its management daemon LXD offer a middle ground between full virtual machines and application containers, providing the isolation of containers with the functionality of traditional VMs.
In 2026, LXC and its modern successor Incus (the renamed and rewritten LXD) continue to serve critical roles in scenarios requiring full system containersโdevelopment environments, testing infrastructure, security sandboxing, and edge computing deployments. This article explores LXC and LXD fundamentals, comparing them with Docker, explaining their architecture, and providing practical guidance for deployment.
Understanding LXC and LXD
LXC provides operating-system-level virtualization through kernel namespaces and control groups (cgroups), allowing multiple isolated Linux systems to run on a single host. Unlike application containers that run a single process, system containers run a complete init system, multiple services, and can host multiple applications.
LXC vs LXD
LXC is the underlying container technologyโthe kernel-level implementation of Linux namespaces and cgroups. LXD is a daemon that provides a REST API and command-line interface for managing LXC containers, similar to how Docker Engine provides the API for application containers.
# Install LXD
# Ubuntu/Debian
sudo apt install lxd
# Or via snap
sudo snap install lxd --channel=latest/stable
# Initialize LXD
sudo lxd init
# This interactive setup configures:
# - Storage pool (dir, lvm, zfs, btrfs)
# - Network bridge
# - Container access
LXC vs Docker
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ LXC SYSTEM CONTAINERS vs DOCKER โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ LXC/LXD โ โ Docker โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Full Linux system โ โ Single application โ โ
โ โ Multiple services โ โ + dependencies โ โ
โ โ Systemd/init โ โ Single PID 1 process โ โ
โ โ SSH, cron, syslog โ โ Minimal filesystem โ โ
โ โ Traditional VMs feel โ โ Microservices focus โ โ
โ โ Longer startup โ โ Instant startup โ โ
โ โ More resources โ โ Minimal resources โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Use Cases: Use Cases: โ
โ - Dev/Test environments - Microservices โ
โ - Full system testing - CI/CD pipelines โ
โ - Security sandboxing - Application packaging โ
โ - Legacy applications - Serverless functions โ
โ - Multi-service applications - Lightweight isolation โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Working with LXD
Container Management
# List available images
lxc image list images:
lxc image list ubuntu:22.04
# Launch a container
lxc launch ubuntu:22.04 mycontainer
lxc launch images:alpine/3.18 myalpine
# List containers
lxc list
lxc list --format=table
lxc list state=running
# Start/Stop containers
lxc start mycontainer
lxc stop mycontainer
lxc restart mycontainer
# Delete container
lxc delete mycontainer
# Access container shell
lxc exec mycontainer -- /bin/bash
lxc exec mycontainer -- ls -la
# Get container info
lxc info mycontainer
Container Configuration
# View container configuration
lxc config show mycontainer
# Edit configuration
lxc config edit mycontainer
# Set resource limits
lxc config set mycontainer limits.cpu 2
lxc config set mycontainer limits.memory 2GiB
lxc config set mycontainer limits.memory.swap false
# Set environment variables
lxc config set mycontainer environment.VAR_NAME value
# Auto-start containers
lxc config set mycontainer boot.autostart true
lxc config set mycontainer boot.autostart.delay 5
Creating Containers from Custom Images
# Import an image
lxc image import rootfs.tar.gz --alias my-custom-image
# Create container from custom image
lxc launch my-custom-image mycontainer
# Export container as image
lxc publish mycontainer --alias my-container-image
Networking
LXD provides flexible networking options for containers.
Network Configuration
# List networks
lxc network list
# Create network
lxc network create mynetwork
lxc network create mynetwork \
ipv4.address=10.10.10.1/24 \
ipv4.nat=true \
ipv6.address=fd42::1/64
# Attach container to network
lxc network attach mynetwork mycontainer eth1
# Container network info
lxc config device show mycontainer
Network Devices
# Add network device to container
lxc config device add mycontainer eth0 nic name=eth0 network=lxdbr0
# Add routed NIC
lxc config device add mycontainer eth0 nic \
nictype=routed \
ipv4.address=10.0.0.50/24 \
ipv4.gateway=10.0.0.1
# Add macvlan
lxc config device add mycontainer eth0 nic \
nictype=macvlan \
parent=eth0
Storage
LXD manages storage through storage pools.
Storage Pools
# List storage pools
lxc storage list
# Create storage pool
lxc storage create mypool dir
lxc storage create mypool zfs source=/dev/sdb1
lxc storage create mypool btrfs source=/dev/sdc1
lxc storage create mypool lvm source=/dev/sda5 vgname=lxd-vg
# Storage pool info
lxc storage info mypool
# Container storage
lxc config device add mycontainer root pool=default size=10GiB
Bind Mounts
# Add bind mount
lxc config device add mycontainer homedir disk \
source=/home/user \
path=/home/containeruser
# Add readonly bind mount
lxc config device add mycontainer config disk \
source=/etc/config \
path=/etc/config \
readonly=true
Snapshots and Backups
LXD supports efficient snapshots using copy-on-write storage.
# Create snapshot
lxc snapshot mycontainer snap1
lxc snapshot mycontainer "pre-update-$(date +%Y%m%d)"
# List snapshots
lxc snapshot list mycontainer
# Restore snapshot
lxc restore mycontainer snap1
# Delete snapshot
lxc delete mycontainer/snap1
# Export container
lxc export mycontainer /backup/mycontainer.tar.gz \
--optimized-storage --compression zstd
# Import container
lxc import /backup/mycontainer.tar.gz
Profiles
Profiles provide reusable configuration for containers.
Working with Profiles
# List profiles
lxc profile list
# Create profile
lxc profile create myprofile
# Edit profile
lxc profile edit myprofile
# Apply profile to container
lxc profile add mycontainer myprofile
# Remove profile
lxc profile remove mycontainer myprofile
Example Profile
# Profile configuration
name: production
description: Production container profile
config:
limits.cpu: 4
limits.memory: 8GiB
security.nesting: "true"
security.privileged: "false"
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: default
type: disk
Security
LXD provides security features for container isolation.
Security Configuration
# Prevent nesting (running containers in containers)
lxc config set mycontainer security.nesting false
# Run in privileged mode (not recommended)
lxc config set mycontainer security.privileged true
# Restrict container capabilities
lxc config set mycontainer security.cap drop-all
lxc config set mycontainer security.cap allow chown
# AppArmor profile customization
lxc config set mycontainer raw.apparmor "deny /proc/sys/fs/binfmt_misc/** w,"
Best Practices
# Never run untrusted containers in privileged mode
# Use unprivileged containers (default in LXD)
lxc launch ubuntu:22.04 untrusted -c security.privileged=false
# Restrict resources
lxc config set mycontainer limits.cpu.allowance 50%
lxc config set mycontainer limits.memory.max 1GiB
# Network isolation
lxc network attach mynetwork restricted-container eth0
Cluster Setup
LXD can be clustered for high availability and scalability.
Cluster Management
# Initialize cluster
lxd init --cluster
# Add node to cluster
lxc cluster add node2
# List cluster members
lxc cluster list
# Manage cluster
lxc cluster remove node2
lxc cluster rename oldname newname
LXC (Command-Line)
For basic LXC usage without LXD daemon:
# Check kernel support
lxc-checkconfig
# Create container
lxc-create -n mycontainer -t download -- --dist ubuntu --release 22.04
# Start/Stop
lxc-start -n mycontainer
lxc-stop -n mycontainer
# Attach to console
lxc-console -n mycontainer
# Monitor
lxc-monitor -n mycontainer
# Freeze/Unfreeze
lxc-freeze -n mycontainer
lxc-unfreeze -n mycontainer
Incus: The Modern LXD
In early 2024, LXD was renamed to Incus while maintaining full compatibility. New installations should use Incus.
# Install Incus
sudo snap install incus
# Initialize Incus
sudo incus init
# Use Incus (same commands as LXD)
incus launch ubuntu:22.04 mycontainer
incus list
incus exec mycontainer -- /bin/bash
# Migration from LXD
lxd migrate-to-incus
Use Cases
Development Environments
# Create isolated development containers
lxc launch ubuntu:22.04 dev-env
lxc config set dev-env \
environment.PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
# Install development tools
lxc exec dev-env -- apt-get update
lxc exec dev-env -- apt-get install -y build-essential git vim
Testing Infrastructure
# Create test environment
lxc snapshot test-container baseline
# Run tests
lxc restore test-container baseline
# Repeat for each test
Multi-Container Applications
# Web application stack
lxc launch ubuntu:22.04 webserver
lxc launch ubuntu:22.04 appserver
lxc launch ubuntu:22.04 database
# Configure networking
lxc network attach internal-net webserver eth0
lxc network attach internal-net appserver eth0
lxc network attach internal-net database eth0
Common Commands Reference
# Container lifecycle
lxc launch images:alpine/3.18 mycontainer
lxc start/stop/restart mycontainer
lxc delete mycontainer
# Information
lxc list
lxc info mycontainer
lxc config show mycontainer
# Access
lxc exec mycontainer -- command
lxc console mycontainer
# Storage
lxc storage list
lxc device add mycontainer data disk source=/data path=/data
# Networking
lxc network list
lxc device add mycontainer eth0 nic network=lxdbr0
# Snapshots
lxc snapshot mycontainer snap1
lxc restore mycontainer snap1
lxc delete mycontainer/snap1
Conclusion
LXC and LXD (now Incus) provide essential capabilities for running full Linux systems in isolated containers. While Docker excels at application containerization, LXC/LXD fills the gap where complete system isolation is neededโdevelopment environments requiring full system access, testing infrastructure needing realistic system behavior, and security applications requiring controlled isolation of entire distributions.
The choice between LXC/LXD and Docker depends on your use case: for microservices and application deployment, Docker remains optimal; for system-level isolation, development environments, and scenarios requiring full Linux functionality, LXC/LXD provides the appropriate solution. Understanding both technologies enables architects and operators to select the right tool for each scenario in modern infrastructure.
Comments