---
title: "Docker without Docker"
description: "Fly.io explains how it accepts OCI container images while avoiding Docker at runtime, choosing Firecracker micro-VMs because Docker’s isolation is not strong enough for its high-density multitenant environment. It describes OCI images as ordered tarball layers, showing how registry authentication, manifests, architecture selection, blob downloads, and configuration data are enough to reconstruct a container filesystem and entrypoint. On the platform side, flyctl uses Docker’s client library to push images, while a custom Go repository server adds token-based authorization, repository rewriting, and handling for cross-repository blob mounts and registry state. Servers use containerd as a cache over an LVM2 thin pool, leases and copy-on-write snapshots to provision VM filesystems quickly, and a Rust init configures mounts, networking, DNS, SSH, and the entrypoint before Firecracker runs the workload."
---

# Docker without Docker

[Fly.io](https://yomu.fyi/company/fly-io) · Apr 8, 2021

**Type:** Explainer

## Summary

Fly.io explains how it accepts OCI container images while avoiding Docker at runtime, choosing Firecracker micro-VMs because Docker’s isolation is not strong enough for its high-density multitenant environment. It describes OCI images as ordered tarball layers, showing how registry authentication, manifests, architecture selection, blob downloads, and configuration data are enough to reconstruct a container filesystem and entrypoint. On the platform side, flyctl uses Docker’s client library to push images, while a custom Go repository server adds token-based authorization, repository rewriting, and handling for cross-repository blob mounts and registry state. Servers use containerd as a cache over an LVM2 thin pool, leases and copy-on-write snapshots to provision VM filesystems quickly, and a Rust init configures mounts, networking, DNS, SSH, and the entrypoint before Firecracker runs the workload.

## Context

Fly.io receives software as Docker containers but operates a high-density multitenant platform where Docker’s isolation is considered insufficient. The system also needs a multitenant container repository with authorization integrated with Fly.io’s API.

## Approach / What changed

The platform accepts OCI images through Docker-compatible tooling, stores them in a custom Go repository server, and converts them into Firecracker micro-VM filesystems. containerd manages image caching and snapshots on an LVM2 thin pool, while a Rust init configures each VM and launches its entrypoint.

## Takeaways

- OCI’s tar-based layers are simple to pull and unpack, but tar has weak standardization, poor random access and incremental-update behavior, and can duplicate large files after small changes.
- The custom repository server wraps Docker registry handlers with authorization middleware; it must rewrite cross-repository blob mounts and \_state URLs, sharing an HMAC key with the registry.
- containerd uses leases for snapshot garbage collection, while LVM2 copy-on-write lets multiple VM instances share image blocks without stepping on one another. Subsequent deployments are faster than the platform’s logging.

**Tags:** [Caching](https://yomu.fyi/topic/caching), [containerd](https://yomu.fyi/topic/containerd), [Docker](https://yomu.fyi/topic/docker), [Firecracker](https://yomu.fyi/topic/firecracker), [Rust](https://yomu.fyi/topic/rust)

- Source: [Fly.io](https://fly.io/blog/docker-without-docker)
- Source URL: https://fly.io/blog/docker-without-docker
- Ingested by Yomu: 2026-09-02T11:58:52.815Z

[Read original post](https://fly.io/blog/docker-without-docker)
