Introduction: LXD – A Lightweight Virtualization Solution on Ubuntu
Hey everyone, if you’ve ever struggled with optimizing resources on an Ubuntu server while still needing multiple independent environments, you’ll surely understand the dilemma of choosing between heavy virtual machines (like KVM) and ultra-lightweight, application-focused containers (like Docker). Personally, after working with various environments for a long time, I’ve found a “sweet spot” with LXD.
LXD isn’t a brand new technology, but it’s an incredibly powerful tool for creating các system container. In simple terms, instead of virtualizing entire hardware like KVM, LXD virtualizes at the operating system level.
Each LXD container is like a full-fledged Ubuntu virtual machine (or any other Linux distro), complete with systemd, SSH, and everything you’d expect, yet it’s extremely lightweight and boots quickly. It shares the Linux kernel with the host, so performance is almost native, and it consumes much less RAM than KVM. When I first switched from CentOS to Ubuntu, it took me about a week to get used to the package management system, and I found the ability to “spin up” a new Ubuntu instance in seconds with LXD for testing to be incredibly convenient.
In this article, I’ll guide you through installing and managing LXD on Ubuntu from A to Z, covering everything from the most basic steps to advanced tips, so you can make the most of this tool for your work.
Quick Start: Install and Run LXD in 5 Minutes
Alright, let’s get straight to it. The goal of this section is to help you get an LXD container up and running in just a few minutes. Prepare an Ubuntu machine (server or desktop works).
1. Install LXD
LXD is distributed as a Snap package on Ubuntu, making installation very straightforward:
sudo snap install lxd
If this is your first time using Snap, it might take a moment to download the necessary components. After installation, add your user to the group lxd so you don’t need to use sudo every time you interact with LXD:
sudo usermod -a -G lxd $USER
newgrp lxd
The newgrp lxd command allows you to apply the changes immediately without logging out and back in.
2. Initialize LXD
Now, we need to initialize the LXD daemon. The lxd init command will guide you through a few basic configuration questions. Most default options are fine for beginners.
lxd init
I usually choose the following (you can press Enter for default options):
Would you like to use LXD in a cluster? (yes/no) [default=no]:noWould you like to create a new storage pool? (yes/no) [default=yes]:yesName of the new storage pool [default=default]:defaultWould you like to use an existing block device? (yes/no) [default=no]:noSize in GB of the new loop device (minimum 1GB) [default=30GB]:(Leave default or enter your desired size, e.g., 10GB if space is limited)Would you like to connect to a bridge interface? (yes/no) [default=yes]:yesWhat should the new bridge be called? [default=lxdbr0]:lxdbr0What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:autoWhat IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:autoWould you like LXD to be available over the network? (yes/no) [default=no]:no (This option is only enabled if you need to manage LXD remotely; it’s not necessary for local installations)Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:yesWould you like a YAML summary of the configuration to be printed? (yes/no) [default=yes]:yes
3. Launch Your First Container
Now, let’s create an Ubuntu 22.04 container and name it my-first-container:
lxc launch ubuntu:22.04 my-first-container
This command will automatically find and download the Ubuntu 22.04 image from the public image repository, then create and start the container. This process usually takes only a few seconds to a minute, depending on your network speed.
4. Check and Access the Container
To check if your container is running:
lxc list
You will see my-first-container with a RUNNING status and an IP address.
To access the shell inside the container:
lxc exec my-first-container bash
Now you’re inside the container! Try apt update, ifconfig, or systemctl status to see it functioning as an independent operating system.
To exit the container, type exit.
5. Stop and Delete the Container
When you no longer need it, you can stop the container:
lxc stop my-first-container
And then delete it:
lxc delete my-first-container
That concludes the Quick Start section! You’ve installed, configured, created, accessed, and deleted an LXD container. Pretty quick and straightforward, right?
Detailed Explanation of LXD
Now I’ll dive a bit deeper so you can better understand the nature of LXD and why it’s so useful.
What is LXD and Why Use It?
LXD is a next-generation system container manager. It’s built upon LXC (Linux Containers) but offers a more user-friendly interface, a powerful REST API, and many advanced management features like snapshots, live migration, and storage/network management.
Key advantages of LXD:
- Lightweight and Fast: Because it shares the Linux kernel with the host, containers boot in seconds and consume very few resources (RAM, CPU) compared to traditional virtual machines. This allows you to run more instances on the same server.
- Full OS Environment: Unlike Docker, which focuses on a single application, LXD provides a complete operating system environment. You can install SSH, systemd, and multiple services on the same container, just like a physical server or a regular virtual machine.
- Security: LXD uses Linux kernel security features like cgroups and namespaces to isolate containers. While not as completely separated as KVM, it still provides a high level of security.
- Easy to Manage: The
lxccommands are intuitive and easy to learn. - Flexible: Supports various storage backends (ZFS, Btrfs, LVM, Directory) and network configurations.
When should you use LXD?
- Running internal services, development/staging environments.
- Testing software on various operating system versions.
- Creating small, lightweight servers for specific tasks (DNS, VPN, monitoring).
- When you need a VM-like environment but have limited resources.
I’ve used LXD to run services like GitLab Runner, Jenkins agents, or even an Nginx reverse proxy instead of setting up KVM because it’s much faster and lighter.
LXD Architecture
LXD operates based on a client-server model. The LXD daemon runs in the background on the host, managing all containers. Users interact with the daemon via the lxc command-line tool or API.
- LXD Daemon: The heart of LXD, running as a system service. It’s responsible for creating, managing, and monitoring containers, and processing client requests.
- LXD Client (`lxc`): The command-line tool for interacting with the daemon.
- Images: Pre-packaged operating system templates (e.g., Ubuntu, Debian, Alpine). LXD has a rich public image repository.
- Instances: Running containers or VMs (LXD also supports KVM virtualization, but we’re focusing on containers here).
- Storage Pools: Where container data is stored.
- Networks: Network configuration for containers, typically via a virtual bridge.
- Profiles: Configuration sets (resources, network, devices) that can be applied to multiple containers.
Basic Installation and Configuration (More Details)
While the quick start section helped you get a container running, a deeper understanding of the configuration options will help you manage LXD more effectively.
System Requirements
LXD runs well on most modern Ubuntu Server or Desktop versions (18.04 or later). The minimum requirements are a few GBs of RAM and a few GBs of disk space.
LXD Initialization (`lxd init`) in More Detail
When you run lxd init, you are configuring the main components of LXD:
- Storage Pool: This is where all container filesystems are stored.
- ZFS: Is the recommended choice as it provides advanced features like snapshots, cloning, and good performance. If you have enough RAM (4GB+ recommended for the host) and want professional storage management, choose ZFS.
- Btrfs: Similar to ZFS, also supports snapshots and cloning.
- Directory: The simplest option, just a directory on the host’s current filesystem. Suitable for test environments or when you don’t need the advanced features of ZFS/Btrfs. However, it doesn’t provide efficient snapshot capabilities like ZFS/Btrfs.
- Network Bridge (`lxdbr0`): LXD will create a virtual bridge network so that containers can communicate with each other and with the outside world. It also integrates a DHCP server to automatically assign IPs to containers. I once encountered a situation where the host had another bridge, and LXD init didn’t automatically detect it, requiring manual configuration of the bridge to the correct subnet, so pay attention if you have a complex network setup.
- Remote Access: An option for the LXD daemon to accept connections from other computers. Only enable when necessary and ensure security.
If you wish to change the configuration later, you can run lxd init again or modify it directly using lxc config commands.
Advanced Container Management
Having covered the basics, let’s now delve into daily container management commands.
Creating and Managing Containers
1. Create a container from an image:
lxc launch ubuntu:22.04 web-server-01
lxc launch images:alpine/3.16 database-01
You can browse available images at images.linuxcontainers.org.
2. List containers:
lxc list
# or with more detailed information
lxc list --columns=ns4,s,t,p
3. Access a container:
lxc exec web-server-01 bash
# Or run a specific command without entering the shell
lxc exec web-server-01 -- apt update
4. Stop, start, restart a container:
lxc stop web-server-01
lxc start web-server-01
lxc restart web-server-01
5. Delete a container:
lxc delete web-server-01
# To delete a running container, add the --force flag
lxc delete web-server-01 --force
Snapshots – Saving Container States
Snapshots are an extremely useful feature, allowing you to save the state of a container at a specific point in time. Excellent for testing or quick backups.
1. Create a snapshot:
lxc snapshot web-server-01 initial-setup
2. List snapshots:
lxc info web-server-01
3. Restore from a snapshot:
lxc restore web-server-01 initial-setup
4. Delete a snapshot:
lxc delete web-server-01/initial-setup
Profiles – Resource and Device Configuration
Profiles are sets of configurations that you can apply to one or more containers. This helps standardize configurations and save time.
1. List profiles:
lxc profile list
2. View profile content:
lxc profile show default
3. Create a new profile (e.g., a profile for a web server with 2GB RAM):
lxc profile create web-profile
lxc profile edit web-profile
In the editor, you add configuration lines to the config: and devices: sections. For example:
config:
limits.memory: 2GB
limits.cpu: 2
devices:
eth0:
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
4. Apply a profile to a container:
lxc launch ubuntu:22.04 my-web-app --profile default --profile web-profile
Or apply to a running container:
lxc profile apply my-web-app default,web-profile
When I first started using LXD, I often forgot to configure network and resource profiles, leading to containers not running as expected. Later, I realized how important it is to dedicate time to lxd init and profiles. This helps me easily manage dev, test, and prod environments with different resources without having to reconfigure each container individually.
Publishing Images – Creating Images from Your Containers
You can create a custom image from an existing container. This is very useful when you have set up and configured a complex environment and want to reuse it.
lxc publish web-server-01 --alias my-custom-web-image --make-copy
Afterward, you can use lxc launch my-custom-web-image new-web-server to create new containers from this image.
Practical Tips and Personal Experience
To make the most of LXD, I’d like to share a few tips:
1. Always Use Profiles
Don’t hesitate to create different profiles for various use cases. For example:
dev-profile: less RAM, less CPU.prod-profile: more RAM, CPU, potentially with additional bind-mounted storage.network-isolated: no external internet connection (internal communication only).
This ensures consistent management and easy scaling.
2. Monitor Resources
You can view container resource information using the command:
lxc info my-container
# Or view real-time statistics
lxc monitor --type=lifecycle
To view CPU, RAM, Network I/O, Disk I/O for all containers:
lxc top
3. LXD Security
- Only enable remote access when absolutely necessary and configure authentication carefully.
- Keep the host OS and container images always updated.
- Do not run untrusted applications inside containers with high privileges.
4. Comparing LXD with KVM and Docker
This is something many people often misunderstand. I’d like to clarify a bit:
- KVM: Is a hardware virtualization solution (Type-1 Hypervisor). It provides complete isolation of virtual hardware, allowing different operating systems (Windows, Linux, BSD) to run. Suitable for environments requiring the highest security, near-native performance for heavy applications, or when you need multiple different OS kernels. Consumes more resources than LXD.
- Docker: Is an application containerization platform. It focuses on packaging a single application and its dependencies into a single container. Extremely fast to start, very lightweight, but does not provide a full operating system environment (no systemd, no default SSH like a VM). Excellent for microservices, CI/CD.
- LXD: Is a bridge between KVM and Docker. It provides a full operating system environment like KVM but is as lightweight and fast as Docker (because it shares the kernel). Suitable for running multiple instances of the same Linux OS, services that require systemd, or when you want a “lightweight VM” without consuming too many resources.
In summary, if you need a true OS, KVM is the best choice. If you only need to run an application, Docker is king. If you need an OS that’s lightweight and fast, LXD is an excellent solution.
Conclusion
LXD is an extremely flexible and powerful tool for lightweight virtualization on Ubuntu. With its ability to create system containers quickly, efficiently, and with easy management, it’s an excellent choice for developers, system administrators, and anyone looking to optimize their servers. I hope that through this detailed guide, you’ll feel confident installing, configuring, and managing LXD for your work. Don’t hesitate to experiment and explore more of LXD’s features!

