Pracandy
← Newsroom

Features

Where Docker Earns Its Keep and Where It Does Not

Container overhead against a single VPS with systemd. When the isolation is worth it.

24 September 2026

A magnifying glass
Photo: PLBechly, CC BY-SA 4.0, via Wikimedia Commons

The Cost of Abstraction

Every container runs its own init process, network stack, and filesystem layer. On a 12GB VPS, these resources add up quickly. When you run five or six containers, the kernel is managing dozens of namespaces and virtual network interfaces. This creates contention for CPU cycles and memory pages. Processes on one box compete for memory, and adding a layer of abstraction means more context switches. If your workload is light, like a static site or a small API, the container overhead can consume a noticeable percentage of your available resources. You are paying for isolation you rarely need. The disk usage also grows because each image layer is stored separately, and pruning them requires active management. On a 193GB disk, this is manageable, but it is still wasted space compared to a native binary.

When Isolation Actually Helps

Isolation earns its keep when a service has complex dependencies or requires a specific runtime version that conflicts with the host. If you need Python 3.8 for one tool and Python 3.11 for another, containers keep them separate. This prevents dependency hell. It also simplifies deployment. You build an image once, and it runs identically on any machine. For a solo developer, this reduces the "it works on my machine" problem. However, for simple services like a Node.js app or a PostgreSQL database, the host environment is usually stable enough. You can pin versions in your package manager or use native version managers. The complexity of managing Docker Compose files, volumes, and networks often exceeds the benefit of the isolation itself. If your services are well-behaved and do not require exotic libraries, native execution is faster and lighter.

The Systemd Alternative

Systemd is the default init system on most modern Linux distributions. It handles process supervision, logging, and service dependencies natively. Instead of a Docker container, you define a unit file. This file tells systemd how to start, stop, and restart your service. It also handles logging via the journal, which is searchable and persistent. For scheduled tasks, systemd timers replace cron. This is cleaner because the timer and the service are linked. If the service fails, the timer logs the error. On our VPS, we run a Next.js process that serves four sites by host-based routing. We also run a separate Node process for an Instagram scheduling tool on port 3050. Both run as native systemd services. There is no Docker daemon running in the background. The memory footprint is lower, and the boot time is faster. Debugging is simpler because you see the exact process ID and resource usage directly in the OS.

Choosing the Right Tool

The decision depends on your specific stack. If you are running a simple web app, a database, and a few background workers, systemd is likely the better choice. It is lighter, faster, and easier to manage. If you are running a complex microservices architecture with many different languages and versions, Docker might be worth the overhead. For an independent studio running a film publication, a wallpaper app, and a few other tools, the simpler approach wins. We serve static builds for our highlight tool and invoice generator directly from disk via Caddy. These have no server process and no database. They do not need containers. The dynamic services run as native processes. This setup is stable, efficient, and easy to maintain. You do not need to learn Docker to run a small production environment. You need to understand your processes and how they interact. Systemd gives you that control without the abstraction layer. Check out PracandyFlix to see what runs on this infrastructure.