LinuxKit

2018/09/09

LinuxKit is a tool that creates custom bootable images locally on your machine based on a simple YAML recipe

Key Facts

How it effects workflow

LinuxKit is fast

Normally the process of creating a bootable image involves starting up an instance, configuring that instance with something like Ansible or Packer or Terraform, then creating a new image from that instance. That process can take a very long time depending on how much configuration is taking place.

Instead, with LinuxKit you can create the image file locally on the machine and push it directly to the cloud. How does LinuxKit make this possible? LinuxKit builds bootable images solely from Docker images.

LinuxKit is concise

Using LinuxKit only requires one simple YAML file to describe your image. Here is a minimal and functional example

kernel:
  image: linuxkit/kernel:4.14.68
init:
  - linuxkit/init:e24105ebb339e1a2e578fde7ec8bccf844a633d5
  - linuxkit/runc:1dc6559fd0a9a332c740312637af0c3fbe6bafa3
  - linuxkit/containerd:ed0589d53e29890b0e504f594a0e4af7326b6484
  - linuxkit/ca-certificates:v0.6
onboot:
  - name: dhcpcd
    image: linuxkit/dhcpcd:v0.6
    command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
services:
  - name: nginx
    image: nginx:1.13.8-alpine
    capabilities:
     - CAP_NET_BIND_SERVICE
     - CAP_CHOWN
     - CAP_SETUID
     - CAP_SETGID
     - CAP_DAC_OVERRIDE
    binds:
     - /etc/resolv.conf:/etc/resolv.conf

You can see in the recipe that every component is already a Docker image, including the kernel. LinuxKit maintains images of the key system components so you don’t have to.

LinuxKit is compatible

Using LinuxKit is incredibly easy since it’s a single Golang binary and is thus cross-platform and has no dependencies. I did all of my LinuxKit experimentation on Windows 10 using Docker for Windows (not Linux Containers for Windows).

LinuxKit is versatile

You have many options for image formats. There are many formats available including aws and gcp. One thing I like about the iso-efi format I chose above is that you can launch instances without any disks for a truly stateless and immutable infrastructure.

PS> linuxkit build -format iso-efi .\linuxkit.yml
Extract kernel image: linuxkit/kernel:4.14.68
Add init containers:
Process init image: linuxkit/init:e24105ebb339e1a2e578fde7ec8bccf844a633d5
Process init image: linuxkit/runc:1dc6559fd0a9a332c740312637af0c3fbe6bafa3
Process init image: linuxkit/containerd:ed0589d53e29890b0e504f594a0e4af7326b6484
Process init image: linuxkit/ca-certificates:v0.6
Add onboot containers:
  Create OCI config for linuxkit/dhcpcd:v0.6
Add service containers:
  Create OCI config for nginx:1.13.8-alpine
Create outputs:
  linuxkit-efi.iso
PS>

The Result

This bootable image will only contain the bare minimum to launch your container

There are always similar tools

RancherOS, Kata Containers, Hyper, LCOW

RancherOS is an OS that, like LinuxKit, is built from containers but instead of being built from scratch, RancherOS is pre-built and you run a container on it.

The Kata Containers project has osbuilder. osbuilder does not look user ready but it appears to be a similar tool for building a bootable machine image from Docker containers.

It’s not clear how Hyper builds their bootable images but the images contain their custom kernel, HyperKernel, and their custom init, HyperStart.

LCOW (Linux Containers on Windows) is the Microsoft offering, using a container runtime called HCS (Host Compute Service) to start containers in a Hyper-V instance.

No container orchestration?

If you already have container images why not just deploy it to a container cluster like ECS or k8s? There are many good reasons:

When it comes to popular orchestration softare like k8s, it should be possible to use these images using KubeVirt or something similar that allows you to launch instances as pods.

In Summary

LinuxKit allows you to quickly and easily build minimal bootable images composed of pre-existing Docker images. This gives you the security of hypervisor isolation and removes the complexities of shared clusters while using familiar tools like Docker.