Ubuntu Server 18.04 – Managing LXD containers

How to install Ubuntu Server 19.10

With Docker out of the way, let’s take a look at how to run containers with LXD. Let’s dive right in and install the required package:

sudo snap install lxd

As you can see, installing LXD is just as easy as installing Docker. In fact, managing containers with LXD is very straightforward as well, as you’ll soon see. Installing LXD gives us the lxc command, which is the command we’ll use to manage LXD containers. Before we get going though, we should add our user account to the lxd group:

sudo usermod -aG lxd <yourusername>

Make sure you log out and log in for the changes to take effect. Just like with the docker group with Docker, the lxd group will allow our user account to manage LXD containers.

Next, we need to initialize our new LXD installation. We’ll do that with the lxd init command: 

lxd init

The output will look similar to the following screenshot:

Setting up LXD with the lxd init command

The lxd init command will ask us a series of questions regarding how we’d like to set up LXD. The defaults are fine for everything, and for the size of the pool, I just used 2 GB but you can use whatever size you want to. Even though we chose the defaults for each of the questions, they’ll give you a general consensus of some of the different options that LXD makes available for us. For example, we can see that LXD supports the concept of a storage pool, which is one of its neater features. Here, we’re creating a default storage pool with a filesystem format of btrfs, which is a filesystem that is used on actual hard disks. In fact, we could even use ZFS if we wanted to, which just goes to show you how powerful this technology is. During the setup process, LXD sets up the storage pool, network bridge, IP address scheme, and basically everything we need to get started.

Now that LXD is installed and set up, we can configure our first container:

lxc launch ubuntu:18.04 mycontainer

With that simple command, LXD will now download the root filesystem for this container and set it up for us. Once done, the container will actually be running and available for use. This is different than Docker, which only sets up an image by default, making us run it manually. During this process, we gave the container a name of mycontainer and based it on Ubuntu 18.04. The process should be fairly easy to follow so far.

You might be wondering why we used an lxc command to create a container, since we’re learning about LXD here. As I mentioned earlier, LXD is a management layer on top of LXC, and as such it uses lxc commands for management. Commands that are specific to the LXD layer will be lxd, and anything specific to container management will be done with lxc.

When it comes to managing containers, there are several types of operations you will want to perform, such as listing containers, starting a container, stopping a container, deleting a container, and so on. The lxc command suite is very easy and straightforward. Here is a table listing some of the most common commands you can use, and I’m sure you’ll agree that the command syntax is very logical. For each example, you substitute <container> with the name of the container you created:



List containers

lxc list

Start a container

lxc start <container>

Stop a container

lxc stop <container>

Remove a container

lxc delete <container>

List downloaded images

lxc image list

Remove an image

lxc image delete <image_name>


With all the basics out of the way, let’s jump into our container and play around with it. To open a shell to the container we just created, we would run the following:

lxc exec mycontainer Bash

The preceding command immediately logs you in to the container as root. From here, you can configure the container as you need to, installing packages, setting up services, or whatever else you may need to do in order to make the container conform to the purpose you have for it. In fact, the process of customizing the container for redeployment is actually easier than it is with Docker. Unlike with Docker, changes are not wiped out when you exit a container, and you don’t have to exit it a certain way to avoid losing your changes. We also don’t have layers to deal with in LXD, which you may or may not be happy about (layers in Docker containers can make deployments faster but when previously run containers aren’t cleaned up, it can look messy).

The Ubuntu image we used to create our container includes a default user account, ubuntu. This is similar to some VPS providers, which also include an ubuntu user account by default (Amazon EC2 is an example of this). If you prefer to log in as this user rather than root, you can do that with this command:

lxc exec mycontainer -- sudo --login --user ubuntu
The ubuntu user has access to sudo, so you’ll be able to run privileged tasks with no issue.

To exit the container, you can press Ctrl + D on your keyboard, or simply type exit. Feel free to log in to the container, and make some changes to experiment. Once you have the container set up the way you like it, you may want the container to automatically start up when you boot your server. This is actually very easy to do:

lxc config set mycontainer boot.autostart 1

Now your newly created container will start up with the server anytime it’s booted.

Now, let’s have a bit of fun. Feel free to install the apache2 package in your container. Similar to Docker, I’ve found that you will probably want to run apt update to update your package listings first, as I’ve seen failures installing packages on a fresh container solely because the indexes were stale. So, just run this to be safe:

sudo apt update && sudo apt install apache2

Now, you should have Apache installed and running in the container. Next, we need to grab the IP address of the container. Yes, you read that right, LXD has its own IP address space for its containers, which is very neat. Simply run ip addr show (the same command you’d run in a normal server) and it will display the IP address information. On the same machine that’s running the container, you can visit this IP address to see the default Apache web page. In case you’re running the container on a server with no graphical user interface, you can use the curl command to verify that it’s working:

curl <container_ip_address>

Although we have Apache running in our container, we can see that it’s not very useful yet. The web page is only available from the machine that’s hosting the container. This doesn’t help us much if we want users in our local network or even from the outside internet to be able to reach our site. We could set up firewall rules to route traffic to it, but there’s an easier way—creating a profile for external access. I mentioned earlier that even though LXD is a containerization technology, it shares some of its feature-set with virtual machines, basically giving you VM-like features in a non-VM environment. With LXD, we can create a profile to allow it to get an IP address from your DHCP server and route traffic directly through your LAN, just as with a physical device you connect to your network.

Before continuing, you’ll need a bridge connection set up on your server. This is done in software via Netplan, and was discussed as part of Chapter 12, Virtualization. If you list your network interfaces (ip addr show) you should see a br0 connection. If you don’t have this configured, refer back to Chapter 12, Virtualization, and refer to the Bridging the virtual machine network section there. Once you’ve created this connection, you can continue on.

Some network cards do not support bridging, especially with some Wi-Fi cards. If you’re unable to create a bridge on your hardware, the following section may not work for you. Consult the documentation for your hardware to ensure your network card supports bridging.

To create the profile we’ll need in order to enable external access to our containers, we’ll use the following command:

lxc profile create external

We should see output similar to the following:

Profile extbr0 created

Next, we’ll need to edit the profile we just created. The following command will open the profile in a text editor so that you can edit it:

lxc network edit external

Inside the profile, we’ll replace its text with this:

description: External access profile
name: eth0
nictype: bridged
parent: br0
type: nic

From this point forward, we can launch new containers with this profile with the following command:

lxc launch ubuntu:18.04 mynewcontainer -p default -p external

Notice how we’re applying two profiles, default and then external. We do this so the values in default can be loaded first, followed by the second profile so that it overrides any conflicting parameters that may be present.

We already have a container, though, so you may be curious how we can edit the existing one to take advantage of our new profile. That’s simple:

lxc profile add mycontainer external

At this point forward, assuming the host bridge on your server is configured properly, the container should be accessible via your local LAN. You should be able to host a resource, such as a website, and have others be able to access it. This resource could be a local intranet site or even an internet-facing web site.

As far as getting started with LXD is concerned, that’s essentially it. LXD is very simple to use and its command structure is very logical and easy to understand. With just a few simple commands, we can create a container, and even make it externally accessible. Canonical has many examples and tutorials available online to help you push your knowledge even further, but with what you’ve learned so far, you should have enough practical knowledge to roll out this solution in your organization.

Comments are closed.