Skip to content

Quickstart

This document acts as a quickstart guide to showcase urunc features. Please refer to the installation guide for more detailed installation instructions, or the design document for more details regarding urunc's architecture.

We can quickly set urunc either with docker or containerd and nerdctl. We assume a vanilla ubuntu 22.04 environment, although urunc is able to run on a number of GNU/Linux distributions.

Using Docker

The easiest and fastest way to try out urunc would be with docker Before doing so, please make sure that the host system satisfies the following dependencies:

  • Docker
  • Qemu
  • urunc and containerd-shim-urunc-v2 binaries.

Install Docker

At first we need docker.

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ rm get-docker.sh
$ sudo groupadd docker # The group might already exist
$ sudo usermod -aG docker $USER

Note: Please logout and log back in from the shell, in order to be able to use docker without sudo

Install urunc from source

Then we need urunc:

$ sudo apt install -y git make
$ git clone https://github.com/nubificus/urunc.git
$ docker run --rm -ti -v $PWD/urunc:/urunc -w /urunc golang:1.23 bash -c "git config --global --add safe.directory /urunc && make"
$ sudo make -C urunc install

A docker example

We will try out a Unikraft unikernel over Qemu.

Install Qemu

Let's make sure that Qemu is installed :

$ sudo apt install -y qemu-system

Run the unikernel

Now we are ready to run Nginx as a Unikraft unikernel using docker and urunc:

$ docker run --rm -d --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/nginx-qemu-unikraft:latest unikernel
67bec5ab9a748e35faf7c2079002177b9bdc806220e59b6b413836db1d6e4018

We can inspect the container and get its IP address:

$ docker inspect 67bec5ab9a748e35faf7c2079002177b9bdc806220e59b6b413836db1d6e4018 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

At last we can curl the Nginx server running inside Unikraft with:

$ curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
  <title>Hello, world!</title>
</head>
<body>
  <h1>Hello, world!</h1>
  <p>Powered by <a href="http://unikraft.org">Unikraft</a>.</p>
</body>
</html>

Using containerd and nerdctl

The second way to quickly start with urunc would be by setting up a high-level container runtime (e.g. containerd) and using nerdctl.

Install a high-level container runtime

First step is to install containerd and setup basic functionality (the CNI plugins and a snapshotter).

If a tool is already installed, skip to the next step.

Install and configure containerd

We will install containerd from the package manager:

$ sudo apt install containerd

In this way we will also install runc, but not the necessary CNI plugins. However, before proceeding to CNI plugins, we will generate the default configuration for containerd.

$ sudo mkdir -p /etc/containerd/
$ sudo mv /etc/containerd/config.toml /etc/containerd/config.toml.bak # There might be no configuration
$ sudo containerd config default | sudo tee /etc/containerd/config.toml
$ sudo systemctl restart containerd

Install CNI plugins

$ CNI_VERSION=$(curl -L -s -o /dev/null -w '%{url_effective}' "https://github.com/containernetworking/plugins/releases/latest" | grep -oP "v\d+\.\d+\.\d+" | sed 's/v//')
$ wget -q https://github.com/containernetworking/plugins/releases/download/v$CNI_VERSION/cni-plugins-linux-$(dpkg --print-architecture)-v$CNI_VERSION.tgz
$ sudo mkdir -p /opt/cni/bin
$ sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-$(dpkg --print-architecture)-v$CNI_VERSION.tgz
$ rm -f cni-plugins-linux-$(dpkg --print-architecture)-v$CNI_VERSION.tgz

Setup thinpool devmapper

In order to make use of directly passing the container's snapshot as block device in the unikernel, we will need to setup the devmapper snapshotter. We can do that by first creating a thinpool, using the respective scripts in urunc's repo

$ wget -q https://raw.githubusercontent.com/nubificus/urunc/refs/heads/main/script/dm_create.sh
$ wget -q https://raw.githubusercontent.com/nubificus/urunc/refs/heads/main/script/dm_reload.sh
$ sudo mkdir -p /usr/local/bin/scripts
$ sudo mv dm_create.sh /usr/local/bin/scripts/dm_create.sh
$ sudo mv dm_reload.sh /usr/local/bin/scripts/dm_reload.sh
$ sudo chmod 755 /usr/local/bin/scripts/dm_create.sh
$ sudo chmod 755 /usr/local/bin/scripts/dm_reload.sh
$ sudo /usr/local/bin/scripts/dm_create.sh

Note: The above instructions will create the thinpool, but in case of reboot, you will need to reload it running the dm_reload.sh script. Otherwise check the installation guide for creating a service.

At last, we need to modify containerd configuration for the new demapper snapshotter:

  • In containerd v2.x:
$ sudo sed -i "/\[plugins\.'io\.containerd\.snapshotter\.v1\.devmapper'\]/,/^$/d" /etc/containerd/config.toml
$ sudo tee -a /etc/containerd/config.toml > /dev/null <<'EOT'

# Customizations for devmapper

[plugins.'io.containerd.snapshotter.v1.devmapper']
  pool_name = "containerd-pool"
  root_path = "/var/lib/containerd/io.containerd.snapshotter.v1.devmapper"
  base_image_size = "10GB"
  discard_blocks = true
  fs_type = "ext2"
EOT
$ sudo systemctl restart containerd
  • In containerd v1.x:
$ sudo sed -i '/\[plugins\."io\.containerd\.snapshotter\.v1\.devmapper"\]/,/^$/d' /etc/containerd/config.toml
$ sudo tee -a /etc/containerd/config.toml > /dev/null <<'EOT'

# Customizations for devmapper

[plugins."io.containerd.snapshotter.v1.devmapper"]
  pool_name = "containerd-pool"
  root_path = "/var/lib/containerd/io.containerd.snapshotter.v1.devmapper"
  base_image_size = "10GB"
  discard_blocks = true
  fs_type = "ext2"
EOT
$ sudo systemctl restart containerd

Let's verify that the new snapshotter is properly configured:

$ sudo ctr plugin ls | grep devmapper
io.containerd.snapshotter.v1           devmapper                linux/amd64    ok

Install nerdctl

After installing containerd a nifty tool like nerdctl is useful to get a realistic experience.

$ NERDCTL_VERSION=$(curl -L -s -o /dev/null -w '%{url_effective}' "https://github.com/containerd/nerdctl/releases/latest" | grep -oP "v\d+\.\d+\.\d+" | sed 's/v//')
$ wget -q https://github.com/containerd/nerdctl/releases/download/v$NERDCTL_VERSION/nerdctl-$NERDCTL_VERSION-linux-$(dpkg --print-architecture).tar.gz
$ sudo tar Cxzvf /usr/local/bin nerdctl-$NERDCTL_VERSION-linux-$(dpkg --print-architecture).tar.gz
$ rm -f nerdctl-$NERDCTL_VERSION-linux-$(dpkg --print-architecture).tar.gz

Install urunc from its latest release

At last, but not least, we will install urunc from its latest release. At first, we will install the urunc binary:

$ URUNC_VERSION=$(curl -L -s -o /dev/null -w '%{url_effective}' "https://github.com/nubificus/urunc/releases/latest" | grep -oP "v\d+\.\d+\.\d+" | sed 's/v//')
$ wget -q https://github.com/nubificus/urunc/releases/download/v$URUNC_VERSION/urunc_$(dpkg --print-architecture)
$ chmod +x urunc_$(dpkg --print-architecture)
$ sudo mv urunc_$(dpkg --print-architecture) /usr/local/bin/urunc

Secondly, we will install the containerd-shim-urunc-v2 binary:.

$ wget -q https://github.com/nubificus/urunc/releases/download/v$URUNC_VERSION/containerd-shim-urunc-v2_$(dpkg --print-architecture)
$ chmod +x containerd-shim-urunc-v2_$(dpkg --print-architecture)
$ sudo mv containerd-shim-urunc-v2_$(dpkg --print-architecture) /usr/local/bin/containerd-shim-urunc-v2

A nerdctl-containerd example

We will try out a Rumprun unikernel running over Solo5-hvt with nerdctl.

Install solo5

Lets install solo5-hvt:

$ sudo apt install make gcc pkg-config libseccomp-dev
$ git clone -b v0.6.6 https://github.com/Solo5/solo5.git
$ cd solo5
$ ./configure.sh  && make -j$(nproc)
$ sudo cp tenders/hvt/solo5-hvt /usr/local/bin

Run the Unikernel!

Now, let's run a Redis unikernel on top of Rumprun and solo5-hvt:

$ sudo nerdctl run -d --snapshotter devmapper --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/redis-hvt-rumprun:latest unikernel

We can inspect the running container to check it's IP address:

$ sudo nerdctl ps 
CONTAINER ID    IMAGE                                                      COMMAND        CREATED           STATUS    PORTS    NAMES
8a415b278a9e    harbor.nbfc.io/nubificus/urunc/redis-hvt-rumprun:latest    "unikernel"    18 seconds ago    Up                 redis-hvt-rumprun-8a415
$ sudo nerdctl inspect 8a415b278a9e | grep IPAddress
            "IPAddress": "10.4.0.2",
                    "IPAddress": "10.4.0.2",
                    "IPAddress": "172.16.1.2",

and we can interact with the redis unikernel:

$ telnet 10.4.0.2 6379
Trying 10.4.0.2...
Connected to 10.4.0.2.
Escape character is '^]'.
ping
+PONG
quit
+OK
Connection closed by foreign host.