Skip to content

Running LXD containers in Macpine

Overview

LXD is a next generation system container manager with support for a wide number of Linux distributions. It provides a simple way to build, test, and run multiple Linux environments across a single machine or multiple compute clusters.

Under the hood, LXD uses LXC, through liblxc and its Go binding, to create and manage the containers. However, LXD relies on a number of Linux kernel features, such as CGroups and kernel namespaces, which aren't natively available on MacOS.

Macpine makes it possible to run LXD/LXC containers on MacOS with support for both amd64 and arm64 processors, through its lightweight virtualisation layer. This workflow makes it easy to develop and test LXD containers locally.

Prerequisites

  1. Install QEMU and macpine
brew install qemu macpine
  1. Install the LXD client
brew install lxc

Launch an LXD instance

Now that that the system is ready, we can create a lightweight Macpine instance, which has been pre-configured to run LXD. In your terminal run:

alpine launch --image alpine_3.16.0_lxd --name lxd --port 8443 --ssh 2222 --mount $(pwd)

This will create a new instance called lxd and forward port 8443 (the default port that LXD client uses to communicate with the LXD server) of the instance to host. Macpine will attempt to match the native CPU architecture of your host to the correct instance image. However, if you can explicitly specify the architecture by adding either --arch aarch64 or --arch x86_64 to the above command. This will mount your current working directory to /root/mnt inside of the lxd instance.

Configure LXD

Before you can create an instance, you need to configure LXD.

Run the following command to accept all automatic defaults:

alpine exec lxd "lxd init --auto"

For the purposes of this tutorial, it is recommended to accept default settings.

NOTE: the above command is executed inside your lxd instance and is sandboxed from your host.

Configure LXD remote

Set up your LXD remote to communicate with the LXD client on your host.

alpine exec lxd "lxc config set core.https_address 0.0.0.0"
alpine exec lxd "lxc config set core.trust_password root"

NOTE: for the purposes of this demonstration, the remote password is configured as root. This password can be configured with lxc config set core.trust_password above

Add the remote to your LXD host:

lxc remote add macpine 127.0.0.1 --accept-certificate --password root

NOTE: if you create an alpine lxd instance, then destroy it, then try to reconfigure another on later on your host, you may need to delete macpine remote from ~/.config/lxc/config.yml due to new certificates each time?

Finally, set this remote as the default:

lxc remote switch macpine

That's it - you can now run LXD containers through Macpine at nearly-native speeds!

Launching your first LXD container

LXD containers can now be launched and manipulated through the lxc client:

lxc launch images:debian/bullseye debian

Mounting host directory -> lxd Macpine instance -> lxd container

lxc config device add debian share disk source=/root/mnt path=/root/mnt

Connecting to your first LXD container

lxc exec debian -- bash

Cleanup

lxc stop debian
lxc delete debian
alpine stop lxd
alpine delete lxd