With LXC and LXD you can run system containers, which are containers that behave like a full operating system (like a Virtual Machine does). There are already official container images for most Linux distributions. When you run lxc launch ubuntu:18.04 mycontainer
, you are using the ubuntu:
repository of container images to launch a container with Ubuntu 18.04.
In this post, we are going to see
- an introduction to the tool
distrobuilder
that creates container images - how to recreate a container image
- how to customize a container image
Introduction to distrobuilder
The following are the command line options of distrobuilder
. You can use distrobuilder
to create container images for both LXC and LXD.
$ distrobuilder System container image builder for LXC and LXD Usage: distrobuilder [command] Available Commands: build-dir Build plain rootfs build-lxc Build LXC image from scratch build-lxd Build LXD image from scratch help Help about any command pack-lxc Create LXC image from existing rootfs pack-lxd Create LXD image from existing rootfs Flags: --cache-dir Cache directory --cleanup Clean up cache directory (default true) -h, --help help for distrobuilder -o, --options Override options (list of key=value) Use "distrobuilder [command] --help" for more information about a command.
The build-dir
command builds the root filesystem (rootfs
) of the distribution and stops there. This option makes sense if we plan to make some custom manual changes to the rootfs
. We would then need to use either pack-lxc
or pack-lxd
to package up the rootfs
into a container image.
The build-lxc
and build-lxd
commands create container images for either LXC or LXD, both from scratch. They both require a YAML configuration file, and that’s what is only needed from them to produce a container image.
Installation
Currently, there are no binary packages of distrobuilder
. Therefore, you will need to compile it from source. To do so, first install the Go programming language, and some other dependencies. Here are the commands to do this.
sudo apt update
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools
Second, download the source code of the distrobuilder
repository (this repository). The source will be placed in $HOME/go/src/github.com/lxc/distrobuilder/
Here is the command to do this.
go get -d -v github.com/lxc/distrobuilder
Third, enter the directory with the source code of distrobuilder
and run make
to compile the source code. This will generate the executable program distrobuilder
, and it will be located at $HOME/go/bin/distrobuilder
. Here are the commands to do this.
cd $HOME/go/src/github.com/lxc/distrobuilder
make
cd
Creating a container image
To create a container image, first create a directory where you will be placing the container images, and enter that directory.
mkdir -p $HOME/ContainerImages/ubuntu/
cd $HOME/ContainerImages/ubuntu/
Then, copy one of the example yaml configuration files for container images into this directory. In this example, we are creating an Ubuntu container image.
cp $HOME/go/src/github.com/lxc/distrobuilder/doc/examples/ubuntu ubuntu.yaml
Finally, run distrobuilder
to create the container image. We are using the build-lxd
option to create a container image for LXD. We need sudo
because the process of preparing the rootfs
requires to set the ownership and permissions of files to IDs that a non-root account cannot perform. Also note the way we invoke distrobuilder
(as $HOME/go/bin/distrobuilder
). It has to be an absolute path because under sudo
the $PATH is different from our current non-root user account.
sudo $HOME/go/bin/distrobuilder build-lxd ubuntu.yaml
It takes about five minutes to build the Ubuntu container image. Be patient.
If the command is successful, you will get an output similar to the following. The lxd.tar.xz
file is the description of the container image. The rootfs.squasfs
file is the root filesystem (rootfs) of the container image. The set of these two files is the container image.
multipass@dazzling-termite:~/ContainerImages/ubuntu$ ls -l total 121032 -rw-r--r-- 1 root root 560 Oct 3 13:28 lxd.tar.xz -rw-r--r-- 1 root root 123928576 Oct 3 13:28 rootfs.squashfs -rw-rw-r-- 1 multipass multipass 3317 Oct 3 13:19 ubuntu.yaml multipass@dazzling-termite:~/ContainerImages/ubuntu$
Adding the container image to LXD
To add the container image to a LXD installation, use the lxc image import
command as follows.
multipass@dazzling-termite:~/ContainerImages/ubuntu$ lxc image import lxd.tar.xz rootfs.squashfs --alias mycontainerimage Image imported with fingerprint: ae81c04327b5b115383a4f90b969c97f5ef417e02d4210d40cbb17a038729a27
Let’s see the container image in LXD. The ubuntu.yaml
had a setting to create an Ubuntu 17.10 (artful
) image. The size is 118MB.
$ lxc image list mycontainerimage +------------------+--------------+--------+---------------+--------+----------+------------------------------+ | ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE | +------------------+--------------+--------+---------------+--------+----------+------------------------------+ | mycontainerimage | ae81c04327b5 | no | Ubuntu artful | x86_64 | 118.19MB | Oct 3, 2018 at 12:09pm (UTC) | +------------------+--------------+--------+---------------+--------+----------+------------------------------+
Launching a container from the container image
To launch a container from the freshly created container image, use lxc launch
as follows. Note that you do not specify a repository of container images (like ubuntu:
or images:
) because the image is located locally.
$ lxc launch mycontainerimage c1
Creating c1
Starting c1
How to customize a container image
The ubuntu.yaml
configuration file contains all the details that are required to create an Ubuntu container image. We can edit the file and make changes to the generated container image.
Changing the distribution release
The file that is currently included in the distrobuilder
repository has the following section:
image:
distribution: ubuntu
release: artful
description: Ubuntu {{ image.release }}
architecture: amd64
We can change to either bionic (for Ubuntu 18.04) or cosmic (for Ubuntu 18.10), save and finally build again the container image.
Troubleshooting
Error “gpg: no valid OpenPGP data found”
$ sudo $HOME/go/bin/distrobuilder build-lxd ubuntu.yaml
Error: Error while downloading source: Failed to create keyring: gpg: keyring/tmp/distrobuilder.920564219/secring.gpg' created gpg: keyring
/tmp/distrobuilder.920564219/pubring.gpg' created
gpg: requesting key C0B21F32 from hkp server pgp.mit.edu
gpgkeys: key 790BC7277767219C42C86F933B4FE6ACC0B21F32 can't be retrieved
gpg: no valid OpenPGP data found.
gpg: Total number processed: 0
gpg: keyserver communications error: keyserver helper general error
gpg: keyserver communications error: unknown pubkey algorithm
gpg: keyserver receive failed: unknown pubkey algorithm
The keyserver pgp.mit.edu is often under load and does not respond. You can edit the YAML configuration file and replace pgp.mit.edu
with keyserver.ubuntu.com
.
Error “gpg: keyserver timed out”
$ sudo $HOME/go/bin/distrobuilder build-lxd ubuntu.yaml
Error: Error while downloading source: Failed to create keyring: gpg: keyring/tmp/distrobuilder.854636592/secring.gpg' created gpg: keyring
/tmp/distrobuilder.854636592/pubring.gpg' created
gpg: requesting key C0B21F32 from hkp server pgp.mit.edu
gpg: keyserver timed out
gpg: keyserver receive failed: keyserver error
The keyserver pgp.mit.edu is often under load and does not respond. You can edit the YAML configuration file and replace pgp.mit.edu
with keyserver.ubuntu.com
.
3 comments
1 ping
Hi Simos, is there any way to include the installation of LXD when generating an Ubuntu image?
I believe that adding “snapd” to the apt packages list in the yaml file will work, but will a “snap install lxd” command defined in the “action” section work? I have seen issues when trying to install anything using snap when running from a chroot environment from a debootstrap generated file system.
this article is saving my behind now 😉
Thanks for the article, how would one create a virtual machine image?
[…] Using distrobuilder to create container images for LXC and LXD […]