Linux containers are revolutionizing how developers deploy and manage applications. Unlike traditional virtual machines that simulate hardware, containers share the host kernel and only virtualize the user space. This makes containers extremely lightweight and fast to spin up.

The Linux Container Project (LXC) offers tools for creating and managing containers on Linux. LXD builds on top of LXC to provide a user-friendly command line and REST API for interacting with LXC containers. This guide will walk through everything you need to know to get started with LXD containers.

What is LXD?

LXD stands for Linux Container Daemon. It serves as a daemon process that manages containers on the host. Specifically, LXD offers:

  • A command line client lxc for creating, starting, stopping and managing containers
  • A REST API for programmatically controlling containers
  • Image management for quickly spinning up containers from existing images
  • Storage management with support for pooling disk resources
  • Network management for creating bridges, NICs, port forwarding rules and more

By installing LXD, you get access to all these features for easily working with LXC containers. The lxc command makes it as simple as:

lxc launch ubuntu:20.04 my-container

To have a container up and running!

Some key advantages of using LXD containers:

  • Fast boot times – Containers share the host kernel and boot in seconds
  • Density – You can run many more containers than VMs on the same hardware
  • Security – Containers isolate processes from the host and each other
  • Portability – Images made on one host export and run on any host with LXD

If you need an environment that boot fast, maximizes hardware resources, keeps processes secure, and remains portable, LXD is an excellent choice.

Installing LXD

LXD offers deb/RPM packages, but the recommended way to install it is using snap:

sudo snap install lxd

This will grab the latest stable release of LXD and set it up on your system.

To allow your non-root user to manage containers, add yourself to the lxd group:

sudo usermod -a -G lxd $(whoami)

Then log out and back in for the group membership to take effect.

With LXD installed, initialize it with:

lxd init

This sets up the LXD daemon, storage pools, networking and configures the host environment for containers generally.

Now you have LXD ready go! Let‘s walk through creating and interacting with containers.

Launching Containers

LXD makes launching containers incredibly easy. For example, to start an Ubuntu 20.04 container named web run:

lxc launch ubuntu:20.04 web

This will grab the Ubuntu 20.04 image and instantiate a container from it called web.

To see all running containers:

lxc list

Which should show:

+-------+---------+------+------+------------+-----------+
| NAME  |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-------+---------+------+------+------------+-----------+
| web   | RUNNING |      |      | PERSISTENT | 0         |
+-------+---------+------+------+------------+-----------+

The web container is active and ready for use!

Let‘s start a CentOS container alongside it:

lxc launch images:centos/8 c8

List containers again:

+-------+---------+------+------+------------+-----------+
| NAME  |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |  
+-------+---------+------+------+------------+-----------+
| c8    | RUNNING |      |      | PERSISTENT | 0         |
| web   | RUNNING |      |      | PERSISTENT | 0         |
+-------+---------+------+------+------------+-----------+

Now we have an Ubuntu 20.04 and CentOS 8 container running side-by-side.

LXD containers feel like an isolated machine. You can login, install packages, configure networking, mount storage – anything you would do on a full VM.

Let‘s login to the web container:

lxc exec web bash

This will drop you into a bash shell inside the container:

root@web:~# 

From here, you can manage the container just like a regular Linux server.

When done, type exit to leave the container shell.

LXD makes it incredibly fast to spin up diverse containers on demand. Next, let‘s look at storage and networking with LXD.

LXD Storage Pools and Profiles

So far the containers we launched are using ephemeral storage from the host itself. This data will be lost when the containers shut down.

For persistent storage, LXD offers storage pools. At init time, LXD configures a default pool called default in /var/snap/lxd/common/lxd/storage-pools.

View current pools with:

lxc storage list

Output:

+----------+-------------+--------+------------------------------------------------+---------+
|   NAME   | DESCRIPTION | DRIVER |                     SOURCE                     | USED BY |
+----------+-------------+--------+------------------------------------------------+---------+
| default  |             | dir    | /var/snap/lxd/common/lxd/storage-pools/default | 2       |
+----------+-------------+--------+------------------------------------------------+---------+

The default directory pool is what containers use by default for storage. This pulls from the host filesystem directly.

We can create additional pools. For example, make a new pool called data backed by a logical volume:

lxc storage create data lvm

And list pools:

+----------+-------------+--------+------------------------------------------------+---------+
|   NAME   | DESCRIPTION | DRIVER |                     SOURCE                     | USED BY |
+----------+-------------+--------+------------------------------------------------+---------+
| default  |             | dir    | /var/snap/lxd/common/lxd/storage-pools/default | 2       |
| data     |             | lvm    | /dev/ubuntu-vg/data                            | 0       |  
+----------+-------------+--------+------------------------------------------------+---------+

The data pool is now defined but not yet used by any containers.

We also have storage profiles that define what pools/volumes to use for container storage.

List profiles with:

lxc profile list

Let‘s copy the default profile to create a new data profile:

lxc profile copy default data

And edit it:

lxc profile edit data

Modify the devices: section to something like:

devices:
  root:
    path: /
    pool: default
    type: disk
  data:
    path: /data
    pool: data
    type: disk

This will make new containers using the data profile mount /data from our new disk pool.

How do we apply profiles to containers? With launch options!

lxc launch ubuntu:20.04 webapp -p default -p data

The -p data option tells LXD to apply the data profile and mount /data from our pool.

Profiles and custom storage volumes give you complete control over persistent container storage.

Up next, managing networks with LXD!

LXD Container Networking

LXD containers come with a default eth0 NIC that gets a random private IPv4 address from LXD itself.

See current networking:

lxc network list
+----------+----------+---------+-------------+------------------------+---------+
|   NAME   |  TYPE   | MANAGED |      IP     |         NETMASK        | USED BY |  
+----------+----------+---------+-------------+------------------------+---------+
| eth0     | physical | NO      | 10.211.55.1 | 255.255.255.0          | 0       |
| lxdbr0   | bridge   | YES     | 10.71.19.1  | 255.255.255.0          | 3       |
+----------+----------+---------+-------------+------------------------+---------+

The lxdbr0 bridge is what containers connect to by default for internal networking. This gives containers a private IP from the LXD managed subnet.

We can manually define additional networks.

For example, let‘s make an new ext bridge attached to the host‘s physical NIC:

lxc network create ext ipv4.address=192.168.1.100/24 ipv4.nat=true ipv6.address=none ipv6.nat=false

And list networks again:

+-------+----------+---------+-------------------+------------------+---------+
| NAME  |   TYPE   | MANAGED |        IP         |      NETMASK     | USED BY |
+-------+----------+---------+-------------------+------------------+---------+
| eth0  | physical | NO      | 10.211.55.1       | 255.255.255.0    | 0       |  
| ext   | bridge   | YES     | 192.168.1.100/24  | 255.255.255.0    | 0       |
| lxdbr0| bridge   | YES     | 10.71.19.1        | 255.255.255.0    | 3       |
+-------+----------+---------+-------------------+------------------+---------+

The ext bridge now exists for containers to use.

We can attach networks to specific containers with:

lxc network attach ext mywebsite

Or define networks directly in profiles.

LXD makes it easy to isolate container networking, define custom bridges, set forwarding rules, NATs, and other policies.

For production LXD, you may want to attach containers directly to Linux bridges on the host for optimal performance rather than use the built-in LXD NAT‘d bridge.

Finally, let‘s look at how to manage and interact with running containers.

Getting Container Info and Stats

Once you have containers up and running, LXD offers plenty of ways to manage them.

To view detailed info on a container, use:

lxc info mywebsite

This prints everything from IP addresses, storage use, memory usage, what profiles are applied and more. Super useful for debugging containers!

You can also monitor resource usage with:

lxc monitor mywebsite

Which will stream near real-time CPU, network and memory usage statistics.

Get a quick overview of all containers with:

lxc list -c nsc

The -c option controls columns printed. This shows us names, IPv4 IPs, and container state.

Starting, Stopping and Restarting

Need to reboot a container? Simple:

lxc restart mywebsite

This does a clean shutdown then boot of the OS inside the container.

Or to start/stop:

lxc stop mywebsite
lxc start mywebsite

These will power down or boot up the container on demand without rebooting the actual OS inside.

Executing Commands

Sometimes you want to run a one-off command or script inside a container. LXD allows this without starting a shell session.

For example, to run top inside a container:

lxc exec mywebsite -- top -b

Anything printed by the top command will be output locally.

Or to cat a remote file:

lxc exec mywebsite -- cat /etc/os-release

Lets you peek inside containers to inspect files or run diagnostics through one-off commands.

When done with a container, clean it up:

Deleting Containers

No longer need a container? Delete it:

lxc delete myoldcontainer 

By default, LXD will unmount and wipe any mounts from associated storage pools too.

So if you created containers using custom storage volumes or profiles, those will cleaned up automatically.

This allows you to rapidly spin containers up and down without leftover storage artifacts.

Where To Go From Here?

That covers the basics of using LXD containers! With the tools above you can:

  • Efficiently create and destroy containers on demand
  • Allocate storage volumes that persist outside containers
  • Define bridges, NAT rules, IP ranges and other networking
  • Interact with containers to query state, exec commands and view logs/metrics

Some directions you could explore next:

  • Storage pools – Create network-mounted storage for containers to use
  • Images – Learn to build custom images with specific packages and config
  • Profiles – Pre-define common configuration like networking and storage
  • Groups – Organize containers into groups for managing at scale
  • Cloud init – Customize containers during launch with cloud-init syntax
  • Scheduling – Automatically restart or scale container counts

LXD provides a vast amount of flexibility for running Linux containers. Combined with the performance of containers vs full VMs, it makes for an extremely compelling platform for deploying applications at scale.

If you need portable Linux environments with near instant launch times and maximum density LXD is hard to beat!

Similar Posts