Skip to the content.
Building a Custom Docker Daemon Engine From Scratch | AI Systems Design From Scratch

Connect with Amin Boulouma Official

AI Systems Design From First Principles - An implementation of AI Systems Design From First Principles | Product Hunt

🏠 Documentation Hub 📝 Engineering Blog 💻 GitHub Repository

Building a Custom Docker Daemon Engine From Scratch

Amin Boulouma — Software Engineer

When you execute a command through a client CLI tool, it communicates directly with a central structural service: the container runtime daemon. In a production environment, this is dockerd. The daemon acts as the stateful engine room of the platform—listening continuously for incoming socket connection packets, validating requests against an internal data schema, spinning up virtual sandboxes, and logging operational status matrices.

By analyzing the daemon as a clean communication layer, we peel back the abstraction of infrastructure automation.

To satisfy our repository’s strict zero-dependency constraint, we will build a stateful, socket-multiplexed container virtualization coordinator server completely from scratch, relying solely on the Python standard library runtime.


The Container Daemon Architecture

Our engine implementation relies on the ContainerManager class. This component coordinates three major architectural states:

  1. Network Demultiplexing: Binding network infrastructure to intercept raw bytes.
  2. Dynamic Request Parsing: Tokenizing incoming stream frames into executable structural steps (run, stop, list).
  3. State Management: Tracking logical cluster workloads within memory boundary dictionaries.

Here is the complete first-principles daemon implementation:

import utils

class ContainerManager:
    def __init__(self, host='127.0.0.1', listen_port=8080):
        self.containers = {}
        self.server_socket = None
        self.listen_port = listen_port
        self.host = host

    def start_server(self):
        """Initializes the listener socket pool and triggers the main listener loop."""
        self.server_socket = utils.create_socket_server(self.host, self.listen_port, 'Container Manager')

        while True:
            # Block thread processing until a new client establishes a socket connection
            self.client_socket, self.client_address = self.server_socket.accept()
            print(f'Connection from {self.client_address}')
            self._handle_client()

    def _handle_client(self):
        """Processes incoming data frames from an active connection pipe sequentially."""
        while True:
            data = self.client_socket.recv(1024).decode('utf-8')
            if not data: 
                break
            print(f'Received data: {data}')
            if not data.strip(): 
                continue

            # Tokenize serialization string into instruction arrays
            parts = data.strip().split()
            if not parts: 
                continue 

            command = parts[0]
            if command == 'run': 
                if len(parts) < 2: 
                    self.client_socket.sendall("Usage: run <container_name>".encode('utf-8'))
                    continue
                self._run(parts)
            elif command == 'stop': 
                if len(parts) < 2: 
                    self.client_socket.sendall("Usage: stop <container_name>".encode('utf-8'))
                    continue
                self._stop(parts)
            elif command == 'list': 
                self._list()
            else:
                self.client_socket.sendall(f"Unknown command {command}".encode('utf-8'))

        self.client_socket.close()

    def _run(self, parts):
        """Allocates resources and assigns an initial active status structure."""
        container_name = parts[1]
        self.containers[container_name] = {
            'status': 'created',
            'file': f'/tmp/{container_name}.txt'
        }
        # Transmit direct network receipt confirmation string
        self.client_socket.sendall(f"Container '{container_name}' created at '{self.containers[container_name]['file']}'".encode('utf-8'))

    def _stop(self, parts):
        """Alters container state mappings to reflect runtime termination."""
        container_name = parts[1]
        if container_name in self.containers:
            self.containers[container_name]['status'] = 'stopped'
            self.client_socket.sendall(f"Container '{container_name}' stopped".encode('utf-8'))
        else:
            self.client_socket.sendall('Container not found'.encode('utf-8'))

    def _list(self):
        """Compiles a complete serialization snapshot of active data fields."""
        clients = []
        for name, info in self.containers.items(): 
            clients.append(f"{name} - {info['status']}")
        self.client_socket.sendall(f"Available containers: {clients}".encode('utf-8'))

if __name__ == "__main__":
    manager = ContainerManager()
    manager.start_server()


Architectural Mechanisms Breakdown

1. In-Memory State Registration

Unlike stateless API microservices, our daemon acts as a single source of truth using a localized tracking matrix: self.containers. When a _run sequence gets processed, the engine mutates this dictionary state. This models exactly how full-scale runtimes store configuration blobs, isolated virtual locations, and system parameters during local execution.

2. Stream Buffer Splitting & Parsing

Data moving over raw network sockets arrives without structural spacing formatting. By extracting string tokens using whitespace parsing checks:

parts = data.strip().split()
command = parts[0]

The server isolates the functional command token and cross-references it against our structural execution blocks. The remaining elements are mapped dynamically as configuration arguments to drive target behaviors.

3. Connection Lifecycles & Resource Cleansing

When the client disconnects or an empty data string block (if not data: break) hits the transport layer, the controller drops out of its command handler loop and drops down to clean up socket allocations. Explicitly closing self.client_socket is crucial for production reliability; without it, file handles remain locked, slowly degrading system resources.


Integration and Network Testing

To launch the daemon locally, make sure your shared network helper components are initialized within your codebase structure.

1. Bootstrap the Shared Socket Utilities

Ensure utils.py contains the matching server initialization routine:

import socket

def create_socket_server(host, port, service_name):
    """Initializes and returns a reusable standard TCP server socket."""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((host, port))
    s.listen(5)
    print(f"{service_name} Daemon actively listening on {host}:{port}")
    return s

2. Execution Testing Sequence

Run the daemon backend within your core terminal instance:

python py_container_manager.py

Now, fire commands using your previously engineered command line interface tool (py_container_manager_CLI_client.py) to see the system parse status updates synchronously:

Container Manager Daemon actively listening on 127.0.0.1:8080
Connection from ('127.0.0.1', 54321)
Received data: run micro_service_node
Received data: list


Infrastructure Scaling Roadmap

While this server engine handles basic state tracking and command interpretation, it is constrained by a synchronous connection blocker: it can only handle a single client payload loop at a time.

To transform this system into a high-throughput runtime simulator, our upcoming milestones target these upgrades:

Connect with Amin Boulouma Official