My work on Docker grew out of earlier work on MirageOS, OCaml and the Xapi / Xen toolstack. We explored how to build systems from reusable, type-safe libraries: network protocols, storage and the machinery for managing VMs. The timeline includes both the papers and the code, back to Melange in 2007.

We used our systems background (and unikernel libraries) to create a seamless "Docker for Mac" and "Docker for Windows" experience. Later the same code evolved into a platform for running containers and AI agents in microVMs and is used across the Docker product suite. Here's a list of some of the things I've worked on, newest first. Almost all of it was done with other people, so where I can I've linked to the code, the blog posts and the papers.

2026
microVMs and containers

2026-03: A Decade of Docker Containers (CACM cover article)

papers & talks

Communications of the ACM cover for A Decade of Docker Containers

Anil Madhavapeddy, Justin Cormack and I wrote up how Docker got from Linux to Mac and Windows, the systems research underneath it, and where things are heading with coding agents. The ACM made a nice video and cover art!

MicroVMs for Docker Sandboxes

networkingVMs & platforms

Agents need to run somewhere where access to the outside is carefully controlled i.e. a "sandbox". The unikernel derived VMM tech used in Docker Desktop is now also the isolation layer in Docker Sandboxes, now enhanced with ultra-fast networking and support for running GUIs safely inside the VMs.

Publication of the Year

networkingpapers & talks

Our ICFP networking paper (see 2025) won the Cambridge Computer Lab Ring's Publication of the Year award.

2025
research reports

2025-04-01: ASPLOS Influential Paper Award

papers & talks

First page of the 2013 Unikernels paper

Our 2013 Unikernels paper won one of the ASPLOS Influential Paper Awards. The Mirage OS libraries from that work are the same ones that ended up inside Docker Desktop.

2024
faster and more compatible

Optimising virtiofs for containers

file sharingVMs & platforms

Although Apple's virtualization.framework is a great general-purpose VMM, there are various ways to optimize specifically for Linux containers. Therefore we created Docker VMM using Apple's lower-level hypervisor.framework, built using a fork of the excellent libkrun project. Filesharing perf improved to the point where a directory search over virtiofs would be "faster than native macOS" if caches are warm. We shipped Docker VMM as a beta in Desktop 4.35.

2023
faster and more efficient

2023-08-17: Resource Saver mode

VMs & platformspapers & talks

In the cloud people often talk about "scaling to zero". I've always been a fan of the principle that your laptop should only be executing code if you actually tell it to, i.e. definitely no battery reducing background polling loops. I built a mechanism for shutting down the Docker Desktop helper VM, keeping it offline as much as possible (e.g. by not booting it up for read API requests) and starting it on demand to actually run containers.

2023-04-27: userspace TCP/IP version 2

networkingVMs & platformsenterprise

I originally switched Docker from kernel networking to a custom userspace stack vpnkit (based on the Mirage unikernel libraries) to work around OS security issues and to allow us to interoperate more easily with corporate firewalls and VPNs. Now it was time to switch Mac again to a google/gvisor-based solution. In our published iperf3 benchmark on a first-generation M1 Mac Mini, throughput went from about 3.5 to 19 Gbit/s — over five times faster.

2022
Docker in the enterprise

Kubernetes beyond dockershim

VMs & platformspapers & talks

Kubernetes was built on top of Docker, but in 2022 the method of talking to Docker was changing. Various misleading headlines saying alarming things like "Kubernetes is deprecating Docker" started appearing so we needed to act quickly. To ensure zero hassle for our users, I migrated Desktop's Kubernetes integration to cri-dockerd. This migration shipped in Desktop 4.7.0. To explain what this all means properly I blogged about it in an April article ahead of Kubernetes 1.24.

One HTTP proxy to rule them all

networkingenterprise

Enterprises often have sophisticated HTTP proxy setups, especially if they operate worldwide. Originally Docker Desktop's handling of HTTP proxies was fragmented, each component doing its own thing. A customer told us the obvious truth, that proxy configuration should be "one and done", not something that needs per-component consideration. I consoliated all proxy handling across the product so every subcomponent behaved identically, irrespective of programming language, and all supported the same feature set. Previously for example one component would support PAC files proxy auth, while another relied on Unix-style environment variables.

2022-01-25: How Docker Desktop Networking works under the hood

networkingenterprisepapers & talks

A common topic when speaking with customers is how exactly Docker Desktop's networking works and how well will it interop with other network products. I wrote a detailed blog post all about the unikernel-inspired userspace networking stack that connects containers to the outside world in Docker Desktop. Later this work was refined and used by Valentin and Julius from CARIAD to produce a white paper.

2021
More Apple Silicon (and policy)

Registry Access Management

networkingenterprise

Businesses want to control which registries their developers can pull from. Inspired by Cilium I defined a network policy and then built an enforcement mechanism using a combination of DNS + eBPF + cgroup hooks.

Apple Silicon support released

VMs & platforms

We shipped the GA version of Apple Silicon support! In the meantime Apple had published a nice higher-level VMM API called virtualization.framework which we intended to become our default. So I added support for this too and it shipped as an experimental choice, while QEMU remained the default.

2020
Apple Silicon

2020-11-29: Early build demonstrates incoming Apple Silicon support

VMs & platforms

The first M1 Macs arrived and Docker didn't run on them yet. I put together the early preview builds: integrating the engine and CLI, fixing startup problems and iterating until the tech preview shipped in December, immediately after the hardware itself shipped. My screenshot of an early build ended up in an AppleInsider post by Malcolm Owen.

DockerCon LIVE: New Docker Desktop filesharing features

file sharingpapers & talks

A talk about the new file sharing on Windows and Mutagen on the Mac, and how they speed up the edit-compile-test loop.

gRPC-FUSE becomes the Mac default

storagefile sharing

After Windows, I brought the gRPC-FUSE file-sharing implementation to the Mac as the default, reducing file-event CPU overhead and allowing shared paths to change without restarting the VM. It shipped as the default in Docker Desktop 2.4.0.0 on 30 September.

I also implemented virtio-blk DISCARD in hyperkit so deleted data could be given back to the host.

2020-01-17: Capturing logs in Docker Desktop

papers & talks

A deep-dive into how the logging system works, joint work with Magnus Skjegstad.

2019
file sharing

2019-12-12: New file sharing implementation in Docker Desktop for Windows

networkingfile sharingpapers & talks

We replaced Samba with FUSE over gRPC over Hyper-V sockets. It's much faster, and file change notifications finally work, so tools that watch for edits (like hot reload) behave properly. I implemented the inotify event injection and spent a lot of time on filesystem semantics and caching. The deep dive explains how it all fits together.

vpnkit: new port forwarder

networking

Rewrote host port forwarding in Go with a simple HTTP control protocol, replacing several slightly different copies with one.

2019-02-25: Addressing Time Drift in Docker for Mac

file sharingVMs & platformspapers & talks

Why the VM's clock drifted away from the Mac's (laptops go to sleep!), why that breaks builds and file sharing, and how we fixed it.

2018
Kubernetes and proxies

Native Windows DNS

networking

I changed Docker Desktop's Windows DNS handling to use the native APIs. Using Windows' own resolver instead of reimplementing its behaviour meant Docker followed the same DNS and VPN rules as other Windows applications.

Kubernetes on Windows

networkingVMs & platforms

Docker for Windows gained Kubernetes. I worked on networking for it, and looked at how to change the VM's IP address without forcing everyone to reset their cluster.

Logging, sockets and named pipes

networking

Added pluggable logging to LinuxKit, building on Magnus Skjegstad's earlier work, and taught vpnkit to forward Unix sockets and Windows named pipes, including connections to services such as the Docker socket.

HTTP proxies on restricted networks

networkingenterprise

I added HTTP proxy modes for networks where only the proxy could resolve DNS, with CONNECT support for TLS traffic and tests for the different request paths. I also built more realistic HTTP proxy tests using host firewalls.

2017
disks that shrink

Don't corrupt the disk

storage

Two hyperkit instances writing to the same disk file is a recipe for corruption. I added locking on the backing file, replacing a fragile separate lock file, and added TRIM for sparse raw disks.

Online disk compaction, enabled by default

storagepapers & talks

Diagram of qcow2 disk storage

I implemented online qcow2 compaction so Docker could return disk space without a restart, enabled it by default, and later used sparse raw disks where APFS made the simpler approach possible. Building on TRIM support from late 2016, the OCaml algorithm recycles clusters in the background while the VM keeps running.

Reaching the host by name

networking

I introduced docker.for.mac.localhost and docker.for.win.localhost so containers could reach services on the host without hard-coded IP addresses. These were precursors to the later host.docker.internal name.

2016
vpnkit

2016-09-20: CVE-2016-4739 in macOS Sierra

networking

With Magnus Skjegstad and Anil Madhavapeddy I found that apps using VMnet.framework could end up with a DNS proxy listening on all network interfaces. Apple fixed it in macOS Sierra and credited us.

2016-01-27: A userspace network stack for Docker for Mac

networking

Lots of early users had VPNs, and VPNs didn't get along with the VM's networking. So I plugged the Mirage OCaml TCP/IP stack into Docker for Mac: Ethernet frames from the VM are turned into ordinary socket calls on the Mac, so as far as the VPN is concerned it's just another app. On 2016-04-18 it became the default. It was open-sourced as vpnkit in May, and I merged the Mac and Windows frontends (using Hyper-V sockets on Windows) in July.

2015
from Xen and Mirage to Docker

Thin-provisioned storage with qcow2

storage

Diagram of qcow2 disk storage

I integrated the Mirage qcow2 block layer into Docker for Mac's VM, giving containers a disk that grew as needed instead of reserving its full size on the laptop. This provided sparse storage even on HFS+, which lacked sparse-file support, and let us offer a thin-provisioned 64 GiB container disk.

Reactive VM configuration with Irmin

VMs & platforms

I integrated Irmin into Docker for Mac to store the VM's configuration, using transactions, snapshots and watches to react to changes. Configuration became versioned data: committing a new memory setting made the VM exit and pick up the change on its next start.

Docker for Mac alpha

file sharingVMs & platforms

Alongside this, I debugged alpha builds and worked out how diagnostics reports should work. Early changes fixed symlinks in shared folders and kept the VM's clock in sync with the host. That code now lives in the LinuxKit repo.

2015-05: Jitsu: Just-In-Time Summoning of Unikernels (NSDI)

networkingVMs & platformspapers & talks

First page of Jitsu: Just-In-Time Summoning of Unikernels

With the Jitsu team, I co-authored a paper on starting small MirageOS unikernels in response to network traffic on Xen/ARM. Shared-memory communication and connection hand-off let services start on demand while masking boot latency. In January I also proposed a simpler Jitsu backend using libxl directly; that PR was an RFC.

2015-02-10: Running Xapi on ARM

VMs & platformsstorage

I added Xapi to the Xen ARM builder, so hosts could upload and run VMs through XenAPI and xe, collect performance metrics, and use thin-provisioned LVM storage. Xapi could run alongside xl and libvirt on the same host.

2015-01-31: Choosing entropy sources for Mirage on Xen

VMs & platforms

I added separate choices for the strongest available Xen entropy source and a weak source for development and experiments. This made the choice explicit in the unikernel configuration.

2015-01-19: OCaml Ctypes for device mapper

storage

I switched camldm from hand-written C stubs to OCaml Ctypes bindings, part of the work on reusable storage tools for Xapi.

2014
Mirage libraries and the Xen toolstack

2014-09-14: Packaging the Xapi toolstack with opam

VMs & platforms

I submitted the Xapi toolstack and its supporting libraries and services to the main opam repository, making the OCaml components available through the same package manager as the wider ecosystem.

2014-08 to 09: Deploying and connecting Mirage unikernels

VMs & platformsnetworking

I taught Mirage to generate a .xe script to upload a unikernel to a host running Xapi, using xe-unikernel-upload. I also made the shared-memory vchan implementation easier to test by functorising its environmental dependencies and adding Unix tests.

2014-07-21: Irmin-backed Xenstore prototype

VMs & platformsstoragepapers & talks

Xenstore controls device configuration while VM I/O uses shared memory

I built a Xenstore prototype using Irmin for transactions and persistence. It recorded both the database and connection state, allowing the server to recover after a restart while VMs kept running. The history could be inspected with git log, and Irmin could merge independent device-configuration transactions without forcing clients to retry. I described the design in a Mirage blog post and the Xenstore TNG talk.

2014-02-01: Indirect descriptors for Xen block I/O

storage

I added an initial implementation of indirect descriptors to the Mirage Xen block driver, extending the way block requests could describe their buffers.

2014-01: Unikernels: The Rise of the Virtual Library Operating System (CACM)

VMs & platformspapers & talks

Communications of the ACM cover featuring Unikernels

Anil Madhavapeddy and I wrote a broader overview of unikernels for Communications of the ACM, explaining the library OS approach and the ideas behind MirageOS.

2013
unikernels for the cloud

2013-12: Reusable storage libraries for Mirage

storage

I worked on the FAT filesystem and Unix/Xen block interfaces, including adding files to FAT images and implementing the common Mirage BLOCK signature in the Xen driver. These libraries let storage code run across different backends.

2013-09: Xen event delivery without periodic polling

VMs & platforms

I changed the Mirage Xen runtime to use asynchronous hypervisor callbacks and event- channel counters. Waiting threads could block and resume without missing notifications, with a timer interrupt handling timeouts.

2013-03: Unikernels: Library Operating Systems for the Cloud (ASPLOS)

VMs & platformsnetworkingpapers & talks

First page of Unikernels: Library Operating Systems for the Cloud

With the Mirage team, I co-authored the paper describing how to compile an OCaml application and the libraries it needs into a small, specialised VM image running directly on a hypervisor. We evaluated network services built this way. The paper later received an ASPLOS Influential Paper Award in 2025.

2012
building the Mirage Xen runtime

2012-12-20: Suspend/resume and multiple network interfaces

VMs & platformsnetworking

I integrated suspend/resume support, Cstruct changes and fixes for multiple virtual network interfaces into the Mirage platform.

2012-09-04: Infrastructure for a Xenstore stub domain

VMs & platforms

I added Xen infrastructure for running Xenstore in a stub domain: a small VM separate from the host control domain. Grant-reference mapping also provided building blocks for device backends and proxies.

2012-04-21: Faster Mirage block I/O

storage

I added multi-page rings and batched requests to the block performance test. On my test storage, this reached about 770 MiB/s for random reads in 512 KiB blocks.

2011
Mirage meets Xapi

2011-08-10: Memory accounting in the Xen toolstack

VMs & platforms

I fixed a memory-management problem in the memory ballooning daemon that could leak host memory when VMs had no balloon drivers, part of the ongoing work on XenServer VM management.

2011-07-15: Mirage deployment through xe

VMs & platforms

I improved Mirage's XCP deployment script to use the xe remote API directly, discover the running VM's UUID from Xenstore, and query block-device information instead of relying on a lookup table.

2010
OCaml in an industrial product

2010-09: Using Functional Programming within an Industrial Product Group: Perspectives and Perceptions (ICFP)

VMs & platformspapers & talks

First page of the XenServer OCaml experience report

Richard Sharp, Thomas Gazagnaire, Anil Madhavapeddy and I reported on using OCaml to build XenServer. We discussed the engineering experience as well as hiring, collaboration and the reactions to using a less mainstream language in a large product team.

2007
type-safe network services

2007-03: Melange: Creating a “Functional” Internet (EuroSys)

networkingpapers & talks

First page of Melange: Creating a Functional Internet

With Anil Madhavapeddy, Alex Ho, Tim Deegan and Ripduman Sohan, I co-authored the Melange paper. We combined OCaml's static typing with generated packet-handling code to build SSH and DNS servers, exploring how type-safe network services could perform competitively with existing C implementations. The work was a precursor to MirageOS.