Docker Engine is a container runtime managed by a root daemon, packaged with a CLI and the Compose plugin for declaring multi-container stacks in YAML. On a self-hosted server it is the substrate almost every other project on this site is distributed for.
Our verdict on Docker Engine#
Docker is boring in the way infrastructure should be, and 29.x is where that stopped being entirely true. Docker Engine 29.0.0 (November 2025) made the containerd image store the default on fresh installs and raised the minimum API version to v1.44, which quietly broke every management tool still speaking an older API; 29.3.0 walked that back to v1.40 in March 2026. Compose jumped from v2 to v5 in the same period and dropped its internal BuildKit builder, so pin the plugin version if your CI depends on build behavior. The real cost is not the daemon, it is that anyone in the docker group is effectively root, and rootless mode buys that back at a price: no ports below 1024 without a setcap on rootlesskit, resource limits only under cgroup v2 with systemd delegation, and no NFS home directory. Run rootful on a single-purpose server; run rootless where the host is shared.
Who Docker Engine is for#
Choose it if
- Anyone following a self-hosting guide, because the guide will hand you a compose file and assume Docker
- A single-purpose home server where one admin owns the box and root equivalence is not a meaningful boundary
- Someone who wants an ecosystem where every project publishes multi-arch images that just run on a Pi 5 and an x86 mini PC alike
Look elsewhere if
- You need containers managed as systemd units with proper dependency ordering; Podman Quadlet does that natively and Docker does not
- The machine has other untrusted users, since group membership in
dockeris a straight path to root - You want a cloud firewall story that works, because Docker's iptables rules bypass UFW rules on published ports
What running it actually looks like#
Add Docker's own apt or dnf repository rather than using the distro package, which is usually several majors behind, then install docker-ce, docker-ce-cli, containerd.io and docker-compose-plugin. Everything after that is a directory of compose files: one folder per stack, a compose.yaml, a .env for secrets and a bind mount for state. Put bind mounts on a path you actually back up, not in a named volume you will forget exists. Nothing needs to exist first except the kernel, though you should set /etc/docker/daemon.json for log rotation before you have gigabytes of JSON logs. Upgrades are apt upgrade and are usually invisible, with the exception of major releases: 29.0 switched fresh installs to the containerd image store, and images built under the old store are not visible after a manual switch.
Resource profile#
- Memory
- 120 MB idle, around 300 MB in ordinary use. dockerd plus containerd on an idle host, before any containers; the number climbs with container count rather than with traffic.
- CPU and acceleration
- Effectively zero at rest; builds and image pulls are the spikes, and BuildKit will happily saturate every core unless you pass a concurrency limit.
- Storage growth
- `/var/lib/docker` grows quietly through dangling images, build cache and stopped containers; a busy host can accumulate tens of gigabytes in a year, and `docker system df` is the only honest accounting.
- Operational load
- 2 of 5, Light. Day to day it is one system service that upgrades cleanly through apt. The attention it costs is the annual major release that changes a default, plus remembering to prune, which puts it at rubric level 2.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Back up your compose files and your bind-mounted data directories. That is the whole story if you have been disciplined. Named volumes live under /var/lib/docker/volumes/<name>/_data and can be copied live for anything that is not a database; for Postgres or MySQL take a dump instead. Images, build cache and container filesystems under /var/lib/docker/overlay2 are regenerable and should be excluded, and they are the bulk of the size. Do not try to back up /var/lib/docker as a unit and expect it to restore; recreate from compose and restore data instead. Keep /etc/docker/daemon.json with the rest.
Derived backup shape
File copy. Copy the config and data directories. Safe while running for anything that writes atomically.
Traps and surprises#
Docker 29 raised the minimum API version and broke tools
Docker Engine 29.0.0 required clients to speak API v1.44 or newer. Management UIs compiled against older API versions started failing with version negotiation errors, which is exactly how CasaOS app management broke for a lot of people. Docker 29.3.0 lowered the floor back to v1.40. If you are pinned on 29.0 through 29.2 and a tool cannot list containers, upgrading Docker is the fix, not downgrading it.
Published ports bypass UFW
Docker writes its own iptables chains, and a container published with -p 8080:80 is reachable from the internet even when ufw says the port is denied. This surprises people who firewalled the host and assumed they were done. Bind to a specific interface (-p 127.0.0.1:8080:80) and put a reverse proxy in front, or use your cloud provider's firewall, which sits outside the host entirely.
Rootless mode cannot bind low ports by default
Rootless Docker runs the daemon in a user namespace, so a container cannot bind 80 or 443. The documented fixes are sudo setcap cap_net_bind_service=ep $(which rootlesskit) followed by a daemon restart, or setting net.ipv4.ip_unprivileged_port_start=0 in sysctl. You also need sudo loginctl enable-linger $USER or the daemon stops when you log out, which is a classic silent-outage-after-reboot.
Resource limits silently do nothing without cgroup v2
In rootless mode, --memory, --cpus and --pids-limit are ignored unless you are on cgroup v2 with systemd. If docker info shows Cgroup Driver: none, your limits are decoration. Even with systemd, only memory and pids are delegated by default; you need a Delegate=cpu cpuset io memory pids drop-in under /etc/systemd/system/user@.service.d/ for the rest.
Docker Desktop licensing does not apply to the server
Docker Desktop requires a paid per-user subscription at companies with 250 or more employees or over 10 million USD in annual revenue. Docker Engine on Linux is Apache-2.0 and carries no such condition. People conflate the two and either pay for something they are not running or assume the whole toolchain has gone commercial. Check which artifact you actually installed before budgeting for it.
Specifications#
- Category
- Platforms and container management
- Licence
- Apache-2.0 (Engine and Compose); Docker Desktop is proprietary (Permissive)
- Written in
- Go
- First release
- 2013
- Maturity
- Mature
- Datastore
- None; image and container metadata under /var/lib/docker, containerd image store by default since 29.0
- Default ports
- none
- Ships as
- apt/dnf repo package, get.docker.com script, static binaries, rootless install
- arm64 builds
- Yes
- Identity
- Not applicable. The daemon has no user accounts; access is whoever can reach the socket, and socket access is root-equivalent.
- Replaces
- VMware Workstation, Heroku, Vagrant
- Project site
- www.docker.com
- Source
- github.com/moby/moby
- Documentation
- docs.docker.com/engine
Alternatives to Docker Engine#
Everything else in platforms and container management, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| CasaOS | 2, Light | 300 MB | Apache-2.0 |
| Podman | 2, Light | 40 MB | Apache-2.0 |
| Unraid | 2, Light | 2048 MB | Proprietary, perpetual per-device licence |
| Coolify | 3, Moderate | 1200 MB | Apache-2.0 |
| Dokploy | 3, Moderate | 900 MB | Apache-2.0, with DSAL 1.0 reserved for a /proprietary path |
| Komodo | 3, Moderate | 250 MB | GPL-3.0 |
Where Docker Engine comes up elsewhere#
Migration guides
Guides
Research
Reference
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.