Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

LXD

Differences Between Docker and Linux Containers

Docker and Linux Containers (such as LXC) both use the same underlying Linux technologies i.e., chroot, cgroups, namespaces, etc. They differ in purpose: Docker focuses on lightweight application containers (typically for microservices), while Linux Containers is intended for full operating system containers.

Docker containers usually run a single process. In contrast, LXC containers behave more like virtual machines, offering a full OS environment.

Originally, Docker used LXC under the hood, but starting with version 0.9, it introduced its own runtime: libcontainer.

Docker emphasized application packaging, automation, and portability: leveraging Dockerfiles, layered filesystems, and compliance with the OCI standard. LXC, on the other hand, targets full system environments.

Linuxcontainers.org project provides LXD, a powerful tool for managing both Linux Containers and virtual machines, offering a CLI experience similar to Docker.

Personally, I prefer LXD for creating virtual machines in development due to its flexibility and Docker-like interface.

Commands

Below we will discuss commands for managing VMs. Same commands will apply for Linux Containers.

Initialization

Initialize LXD for first time use:

lxd init

Images & Remote Image Servers

List remote repository/servers available to pull images.

lxc remote list

List images from a particular remote repository

lxc image list REPOSITORY_NAME:

Search images using keyword MATCH from a remote repository

lxc image list REPOSITORY_NAME: MATCH
# lxc image list ubuntu-minimal:noble

Copy an image from remote repository.

lxc image copy REPOSITORY_NAME:IMAGE_ALIAS_OR_FINGERPRINT local: --alias ubuntu-focal
# lxc image copy ubuntu-minimal:52dd513b467a local: --alias ubuntu24
# lxc image copy ubuntu-minimal:ec0518e181c5 local: --alias ubuntu22

Now, List images locally

lxc image list

Delete a local image:

lxc image delete IMAGE_ALIAS_OR_FINGERPRINT

(Also checkout lxc image export and lxc image import)


Container & VM Management

List all containers/virtual machine

lxc list

Launch/run a virtual machine (use virtual machine image type)

lxc launch REPOSITORY_NAME:IMAGE_NAME VM_NAME
# lxc launch ubuntu24 myvm

Open shell in a virtual machine

lxc exec VM_NAME /bin/bash
# lxc exec myvm /bin/bash

Open console in a virtual machine

lxc console VM_NAME

Stop a virtual machine

lxc stop VM_NAME

Start a virtual machine

lxc start VM_NAME

Restart a virtual machine

lxc restart VM_NAME

Delete a virtual machine

lxc stop VM_NAME
lxc delete VM_NAME

Copy an instance to create a new instance.

lxc copy VM_NAME NEW_CONTAINER_COPY_NAME

Migrate or move an instance to different name/location

lxc move VM_NAME NEW_NAME
lxc move VM_NAME HOST:NEW_NAME

Configure VM/Containers

Set limit for memory of a container/virtual machine

lxc config set VM_NAME limits.memory 1GB

Set limit for cpu for a container/virtual machine

lxc config set VM_NAME limits.cpu 2

Set CPU Pinning for a container/virtual machine

lxc config set VM_NAME limits.cpu 2,3-5

Show all config for a container/virtual machine

lxc config show VM_NAME

Edit config for a container/virtual machine

lxc config edit VM_NAME

List devices attached to a container:

lxc config device list CONTAINER_NAME

Remove a device:

lxc config device remove CONTAINER_NAME DEVICE_NAME

Profiles

A profile contains config, storage volumes, network interfaces details. They are templates to spin-up new instances. They are alternative to manually modifing config for each instance. List profiles

lxc profile list

Get details of a profile

lxc profile show PROFILE_NAME

Copy a profile

lxc profile copy PROFILE_NAME NEW_PROFILE_NAME

Use profile to launch an instance launch/run a container/virtal machine

lxc launch REPOSITORY_NAME:IMAGE_NAME CONTAINER_NAME --profile PROFILE_NAME

Edit a profile

lxc profile edit PROFILE_NAME

Copying Files with Host

COPY a file from host to instance

lxc file push /path/to/file CONTAINER_NAME/target/path/for/file

COPY a file from instance to host

lxc file pull CONTAINER_NAME/path/to/file /new/path/on/host

Mount a directory from host to instance

lxc config device add CONTAINER_NAME NEW_DEVICE_NAME disk source=PATH_ON_HOST(/home/ubuntu) path=TARGET_PATH_IN_CONTAINER

LXD inside LXD

For running lxd inside lxd, make sure following settings are configured to the parent lxd instance

lxc config set CONTAINER security.priviledged true
lxc config set CONTAINER security.nesting true

Snapshots

Create a snapshot of a container

lxc snapshot CONTAINER_NAME NAME

Get details/status of a container; this also shows all snapshots that container has.

lxc info CONTAINER_NAME

Delete a snapshot of a container

lxc delete CONTAINER_NAME/SNAPSHOT_NAME

Restore a snapshot, i.e. rollback container to previous state

lxc restore CONTAINER_NAME SNAPSHOT_NAME

Network Management

List Networks

lxc network list

Show network details

lxc network show NETWORK_NAME

Create a new bridge network

lxc network create lxdbr1

Attach container/virtual machine to a network

lxc network attach NETWORK_NAME CONTAINER_NAME

Attach container/virtual machine from a network

lxc network detach NETWORK_NAME CONTAINER_NAME

DNS to ping between containers/virtual machines. Service discovery similar to docker and k8s:

lxc exec CONTAINER_1 -- ping CONTAINER_2_NAME.lxd

Storage Management

List storage pools:

lxc storage list

Show details of a storage pool:

lxc storage show POOL_NAME

Create a new storage pool:

lxc storage create POOL_NAME zfs size=10GB

Delete a storage pool:

lxc storage delete POOL_NAME

Cloud-init

Launch container/virtual machine with cloud-init

lxc launch IMAGE_NAME VM_NAME --config=user.user-data="$(cat my-cloud-init-data.yaml)"

Next, Verify cloud-init:

lxc exec VM_NAME bash

# 1. Check cloud-init status
$ cloud-init status --wait

# 2. Fetch cloud-init data
$ cloud-init query userdata

# 3. Validate cloud-init schema
$ cloud-init schema --system --annotate

# 4. Verify changes were applied



< Go to Home >