Skip to content

Images and the Registry

Unikraft Cloud (UKC) uses a registry to store the images used to instantiate apps from. At a high level, a user uses kraft to build and push an image to the registry, and then to ask the controller to start an app from it. The steps involved are illustrated in this diagram:

Unikraft Cloud registry

  1. build: The app is built, locally, according to a Dockerfile.
  2. pkg: The app is packaged, locally, into an OCI image.
  3. push: The OCI image is pushed to the UKC registry.
  4. create: Your app is instantiated from the image accoring to a Kraftfile.

The simplest way to run this workflow is to use kraft cloud deploy, which subsumes all of these steps into a single command. Under the hood, the deploy command uses other sub-commands to carry out the work of the different steps, though we won’t bother you with them here πŸ˜€. Note that the service in the diagram is UKC’s mechanism to connect apps to the Internet; read more about that in this guide.

In this guide we’ll use a Python app as a running example to show a number of workflows:

  1. How to create an image and launch an instance from it.
  2. How to create an image and launch multiple instances from it.
  3. How to launch instances from an existing image.

Finally, we will explain the use of Dockerfile and Kraftfile files in the process, as well as what a runtime means.

Let’s get started!

Workflow1: Create an Image and an Instance from it

We will start with the simplest workflow: create an image from a Python app, as per the Python app guide, and start an instance from it, all with a single kraft cloud deploy command:

Terminal window
git clone https://github.com/unikraft-cloud/examples
cd examples/http-python3.12
kraft cloud deploy -p 443:8080 -M 512 .

The output should be similar to:

Terminal window
[●] Deployed successfully!
β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ name: http-python312-ma2i9
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ uuid: e7389eee-9808-4152-b2ec-1f3c0541fd05
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€ state: running
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ url: https://young-night-5fpf0jj8.fra0.kraft.host
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€ image: [username]]/http-python312@sha256:278cb8b14f9faf9c2702dddd8bfb6124912d82c11b4a2c6590b6e32fc4049472
β”œβ”€β”€β”€β”€β”€ boot time: 15.09 ms
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ memory: 512 MiB
β”œβ”€β”€β”€β”€β”€β”€β”€ service: young-night-5fpf0jj8
β”œβ”€β”€ private fqdn: http-python312-ma2i9.internal
β”œβ”€β”€β”€β”€ private ip: 172.16.3.3
└────────── args: /usr/bin/python /src/server.py

This command uses the Kraftfile and Dockerfile files in the directory to build an image named http-python312@sha256:278cb8b1..., package it, push it to the registry and request Unikraft Cloud to start an instance named http-python312-ma2i9 from it (causing the controller in the diagram at the top to fetch the image from the registry in order to start the instance).

You can see your images by running the following command:

Terminal window
kraft cloud image ls

You should see output similar to:

[username]]/http-python312 latest 77 MB

And you can remove an image from the registry via:

Terminal window
kraft cloud img rm http-python312

Workflow2: Create an Image and Multiple Instances from it

For the next workflow, we’ll once again use kraft cloud deploy but this time we’ll use the -R flag to start multiple instances from it:

Terminal window
git clone https://github.com/unikraft-cloud/examples
cd examples/http-python3.12
kraft cloud deploy -p 443:8080 -M 512 -R 2 .
Terminal window
[●] Deployed successfully!
β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ name: http-python312-8mxq5
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ uuid: 37f5b23c-0996-45fa-8d7f-e6b2942eb6fb
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€ state: running
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ url: https://small-darkness-4t9y8n5s.fra0.kraft.host
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€ image: http-python312@sha256:5b922dfa1632af38c476b98fdd9f4314fb9c5e587d3d31255e6479108c057e88
β”œβ”€β”€β”€β”€β”€ boot time: 153.65 ms
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ memory: 512 MiB
β”œβ”€β”€β”€β”€β”€β”€β”€ service: small-darkness-4t9y8n5s
β”œβ”€β”€ private fqdn: http-python312-8mxq5.internal
β”œβ”€β”€β”€β”€ private ip: 172.16.6.7
└────────── args: /usr/bin/python3 /src/server.py

You can check that it worked by listing all instances with:

Terminal window
kraft cloud instance list
NAME FQDN STATE CREATED AT IMAGE MEMORY ARGS BOOT TIME
http-python312-w4bcp sparkling-surf-qphxdk0j.fra0.kraft.host running 45 seconds ago http-python312@sha256... 512 MiB /usr/bin/python3 /src/server.py 153794us
http-python312-juvv4 old-brook-v3bf7h7z.fra0.kraft.host running 45 seconds ago http-python312@sha256... 512 MiB /usr/bin/python3 /src/server.py 154744us
http-python312-8mxq5 small-darkness-4t9y8n5s.kraft.host running 45 seconds ago http-python312@sha256... 512 MiB /usr/bin/python3 /src/server.py 153646us

Note there are 3 running instances in total: the one we created plus the 2 replicas.

Workflow3: Create Instances from an Existing Image

In this final workflow, we’ll take the image we created above and use it to start new instances using the kraft cloud instance command:

Terminal window
kraft cloud instance create \
--start \
--port 443:8080 \
-M 512 \
[username]/http-python312@sha256:1b815914eb568a06ca4bbfdfb7d6cf484a9e9a0947ba8e0e0f1664d972a25bca

That’s it, now you have a shiny new instance from the image you had previously created.

Dockerfiles, Kraftfiles and Runtimes

On Unikraft Cloud, the process of building images is guided by a Dockerfile, and the process of deploying the resulting image by a Kraftfile.

Let’s use once again our Python running example:

Terminal window
git clone https://github.com/unikraft-cloud/examples
cd examples/http-python3.12

The directory contains the following Kraftfile:

spec: v0.6
runtime: python:3.12
rootfs: ./Dockerfile
cmd: ["/usr/bin/python3", "/src/server.py"]

The file is pretty simple, stating what the cmd for starting the application should be, that a Dockerfile should be used to build its root filesystem, and that the python3.12 runtime should be used. On UKC, a runtime is a base image that contains the (minimal) code needed for the application (in this case the Python interpreter) to run; your application code is then overlayed on top of it during the packaging step.

The Dockerfile itself for our app looks as follows:

FROM scratch
# Python HTTP server
COPY ./server.py /src/server.py

If you’re familiar with Dockerfiles there shouldn’t be anything too mysterious in them, other than by default we use FROM scratch to ensure that the resulting images are as lean as possible. To add your app’s code to the build modify the COPY commands as needed.

All guides on UKC, and the examples they rely on underneath come with Kraftfiles and Dockerfiles for you to easily get started.

Learn More