LXD is a next generation container manager that provides additional features that are similar to virtual machines, such as snapshots, storage pools, and more. Using Linux containers (LXC) as the container type, LXD gives you the best of two worlds. In this video, I’ll go over the basics of LXD. You’ll learn how to set it up and launch containers. For this particular video, we’ll focus on LXC commands – but a follow-up that dives more into LXD’s more advanced features is a possibility if there’s enough interest.
All of the commands I’m going to be using will be run against a server running Ubuntu Server 20.04. but, you don’t have to be running Ubuntu. If you’re not a fan of Ubuntu, then Debian is also a good choice. Other distributions are supported as well. Basically, any distribution of Linux with access to the snapd package should work just fine.
The first thing I recommend you do, is to create a user for yourself if you don’t already have one. If you are running Ubuntu and installed it manually, then you would’ve already created a user during installation and you won’t need to do this. Some providers of Ubuntu Server, especially VPS providers, will often give you access to the root account and leave it up to you to create a user. So, if you’re logging into the server as root, consider creating a user for yourself.
To do that, run the following command:
We should add the user to the
sudo group as well:
usermod -aG sudo myusername
We can switch to the newly created user with the following command:
su - myusername
Next, I always recommend starting out with a fully updated server. So make sure you’ve installed all available updates. On Ubuntu, Debian, and related distros, the following commands will do the trick:
sudo apt update && sudo apt dist-upgrade
If there were updates on your end, you should reboot your server to make sure that everything is fresh:
Let’s get LXD installed and running. First, we need to make sure that we have support for snap packages:
If you get no response from this command, then that means your server doesn’t have support for snap packages. At least not yet.
Snap packages are a type of universal package, which is a package type that is not specific to any one distribution of Linux. A developer can publish their application as a snap package, and any distribution that supports snap packages will be able to install it. And quite a few distributions are supported.
Ubuntu Server often gives you this by default, but depending on where your Ubuntu server installation came from, you may need to set it up.
On Ubuntu, distributions based on Ubuntu, as well as Debian, we can run the following command to set up snap packages:
sudo apt install snapd
For other distributions, you can browse to the following URL to set up
If you already had
snapd installed, next check to see if LXD is already present on the system:
The snap list command gives you a list of all the snap packages that you have installed. If you have a bunch, you can narrow down the list:
snap list | grep lxd
If you’ve only now set up
snapd, you won’t have any snaps installed. Either way, you can install LXD with the following command:
snap install lxd
Although it’s optional, adding yourself to the
lxd group will allow you to manage LXD without needing to use
sudo usermod -aG lxd
Now that we have LXD installed, we need to initialize it to get it going:
sudo lxd init
The first prompt will ask us if we’d like to enable clustering. I’m going to say no here, that’s beyond the scope of the tutorial. Just keep in mind that clustering is a possibility, and is highly recommended if you are running LXD in production.
Next, it’s asking us if we would like to set up a new storage pool. This is one of my favorite features of LXD, the storage options are awesome. We’ll definitely want to create a new pool.
The third question will ask us for the name of the pool. I’ll just leave it as “default” here.
Now it’s asking us for the type of storage we want to use. ZFS is default, and it’s a really great choice. But you’ll want a dedicated disk for this, and not everyone will have a second disk on their system. ZFS is recommended if you can though. I’m going to choose dir here, but make a note of the other options here in case you want to try something else later.
It’s asking us if we would like to connect to a MAAS server. This is beyond the scope of today’s video, but it is something I am thinking about covering in a separate tutorial. If you’d like me to do a video on MAAS, click the like button and drop a note in the comments. If enough people ask, I’ll definitely consider it.
Now it’s asking us if we would like to create a new bridge. I’m going to keep the default of yes for this.
And I’m also going to leave the default name of lxdbr0. I’ll keep the default of auto here as well. LXD gives you full flexibility as far as how you set up networking, so as you get more advanced with it, you may want to consider setting up a dedicated network at some point.
For ipv6, I’m going to leave that as the default as well.
Next, it’s asking us whether or not we’d like the LXD server to be available from the outside. I’m going to leave this as no, you should never make something externally available until it’s fully vetted and you’re going to start using the service in production. And this mindset isn’t specific to LXD, I don’t care what it is. Keep it private until you run into a use-case that requires otherwise.
I’m going to accept the defaults for the rest.
Now, lets check out some basic commands we can use.
lxc list will give us a list of the containers we have on our system as well as their status, but right now we haven’t created any yet.
To create a container, we’ll need to find an image we want to base our container on. Images come from ‘remotes’, and the following command will give us a list of remote repositories we have available to us:
lxc remote list
For listing images that are available on a remote, we can use the following command for that:
lxc image list images:
Note the colon at the end.
You can add a search term at the end if you want to search for an image based on a specific distribution:
lxc image list images: debian
You can also add additional search terms to narrow down the list, so if I wanted to list Ubuntu images that are from 20.04, I can add its release code-name here:
lxc image list images: ubuntu focal
To launch a container, the following command will do the trick:
lxc launch images:ubuntu/focal ubuntu
I’m going to create a Debian instance also:
lxc launch images:debian/10 debian
Now that we’ve created a container, the image for that container will be available on our server for faster access. You can see a list of images that are available locally with the following command:
lxc image list
Now that we have a container, we can run a command against it:
lxc exec mycontainer -- apt install apache2
When you run a command against your container, it will run the command, and then exit.
Notice the double hyphen – that separates
lxc commands from commands that are intended to be run from the container.
We now have Apache installed on the container. We can actually curl its IP address and we should see the output of Apache’s default page:
curl <ip address>
As you can see, we can see the code from Apache’s start page. If the container was allowed to be externally available, we would be able to view that start page from outside the server.
Now that we have a container running, we should take a look at commands we can use to start, stop, and restart it.
First, grab a list of the current containers:
To stop a container:
Now the state of that container will show “stopped”:
To start it back up:
We can also restart a container as well:
One of the biggest differences between Docker containers and LXD is that the containers are stateful. This means that since we restarted our container after installing apache, we still have apache on that container. LXC containers, which is the underlying technology with LXD, are almost like virtual machines in nature. They are containers, so they are light weight, but contents on their filesystem are going to be more Linux-like than container-like.
Next, let’s look at deleting containers. That’s simple actually. First, we’ll stop the container:
Couldn’t be any simpler than that.
One of my favorite things to do is to create snapshots of containers, so I can test configuration changes and roll them back if for some reason things don’t go as planned. This is another aspect of LXD containers that are similar to virtual machines in behavior.
To take a snapshot, we can use the
lxc snapshot command:
That’s done. Now let’s check the container list again:
Notice that the snapshot count is now 1.
lxc info command will show us the snapshots that exist for a container:
lxc info <container name>
We get quite a bit of useful information here, not just a list of snapshots. At the bottom, we can see snapshots by name. Note that this section will not be shown if there are no snapshots.
Let’s take a look at setting resource limits. You definitely don’t want to allow a container to saturate your servers RAM if something spirals out of control.
lxc config set <container name> limits.memory 1GB
We can see the current configuration for a container with the following command:
lxc config show <container name>
You can set the limit to whatever you want it to be.
Another thing you might want to consider doing, is setting up the container to automatically start when the server boots up.
lxc config set boot.autostart 1
Now in the info printout, a new line will appear showing that autostart is enabled:
lxc config show <container name>
Something to consider is that you may not want a container to start right away. For example, maybe you have a container that acts as a database server, and that one needs to be online first. You can add a delay to the container to make sure it doesn’t immediately start:
lxc config set boot.autostart.delay 30
Or, you can set a startup order if you want to be very specific:
lxc config set boot.autostart.order 8