Introduction

In order to get a clean working environment, you should develop and test your systems in containerized environments. Multiple solutions exist such as LXD, Docker, CRI-O, Podman which all enables users to run applications in isolated containers.

Container stack (information that need to be confirmed):

  • Docker: Docker > containerd > (+shim) -(OCI spec)-> runC > LXC > cgroups/namespaces
  • CRI-O: Kubernetes -(CRI API)-> CRI-O -(OCI spec)-> runC > LXC > cgroups/namespaces
  • LXD: LXD > LXC > cgroups/namespaces

FYI: runC is written in Go and LXD in written in C

Here I will present LXD, an open-source solution maintained by Canonical. LXD is a system daemon that provides an interface (REST API) used to manage and connect to an LXC container through liblxc library, while being responsible for handling networking, data storage, and managing multiple LXC containers. (LXC can run as a standalone tool but it is somehow limited.)

LXD is mostly adapted to system containers (as opposed to Docker which is mostly adapted to application container).

Installation

On an Ubuntu 22.04.2 LTS OS, run:

lxd init

Follow the instruction (default value should are fine but I personally enables network access to the containers).

Launch a new ubuntu container:

lxc launch images:ubuntu/jammy u1 #add "-p myProfile" for a specific profile

Check instantiated containers state:

lxc list

You also might want to create ufw rules to allow LXD bridge interface:

sudo ufw allow in on lxdbr0
sudo ufw route allow in on lxdbr0 
sudo ufw reload

Images

The list of available images hosted on images: is presented on: https://images.linuxcontainers.org/

or by running:

lxc image list images:

And local images are listed with:

lxc image list

To get an Ubuntu Mantic Minotaur image locally from images: (an set it with ubuntu2310 alias), run:

lxc image copy images:ubuntu/mantic local: --alias ubuntu2310

To export an image to a .tar.gz:

lxs image export myimage .

You can also explore the image:

tar -xzvf <xxxxxxxx>.tar.gz

Edit it and (especially templates and rootfs) and regenerate the archive:

tar -czvf import.tar.gz *

Then import the tunned image into your local: images:

lxc image import import.tar.gz --alias tunedImage

Containers

Containers are instantiated images.

info

To get information relatives to a container:

lxc info u1

start

To start a container, simply run:

lxc start u1

exec

When in a running status you can interact with containers:

lxc exec u1 -- sh

file sharing

To send files to a container:

lxc file push file_to_push.txt u1/path/in/container/

To receive a file from the container:

lxc file pull u1/path/to/file_to_pull.txt /tmp/

To mount a shared directory between host system and the container:

lxc config device add u1 u1dev disk source=/tmp/ path=/host/tmp 

This mount /tmp/ host directory onto /host/tmp/ folder of the container.

snapshot

To take a snapshot of a container:

lxc snapshot u1 backup1

snapshots list is available with lxc info u1

To restore a snapshot:

lxc restore u1 backup1

stop

To set the container with stopped status:

lxc stop u1

copy

To copy a container with stopped status:

lxc copy u1 u1Copy # with -f option to stop at the same time

publish

To turn a container (or a snapshot) onto an image:

lxc publish u1 --alias u1Published # with -f option to stop at the same time (and relaunch it is it was running)

delete

When a container is stopped, you can delete the container:

lxc delete u1 # with -f option to stop at the same time (delete while running)

exposing container port to the outside world

To route specific port 80 from a container to the outside 8888 port:

lxc config device add u1 myPort80ProxyDevice proxy listen=tcp:0.0.0.0:8888 connect=tcp:127.0.0.1:80

LXD/LXC remote access

Check the configuration on the server you can to remotely access:

lxc config edit

You can set export EDITOR=vim (even in your .profile) to use vim instead of nano.

List remote systems on the client:

lxc remote list

Add a new remote (corresponding to the server) on the client:

lxc remote add myRemote <ip_address>:<port(8443)> --password <password>

List containers running on the remote:

lxc list myRemote:

List images hosted on the remote:

lxc image list myRemote:

Previous commands in the part about containers and images should work with myRemote:.

Storage

list existing storage pools

lxc storage list

get storage pool information

lxc storage show myStorage

create a new storage pool

lxc storage create myStorage dir source=/home/user/storage

Profile

list existing profiles

lxc profile list

create and edit a new profile

lxc profile create myProfile
lxc profile edit myProfile

change container profile

lxc profile remove u1 default 
lxc profile assign u1 myProfile