The honest answer is no — Docker by itself is not a sufficient security boundary between untrusted tenants, and treating it as one is how multi-customer hosting platforms get breached. This is not a knock on Docker; it is a statement about what Docker was designed to do. If you are hosting your own apps, the distinction rarely bites. If you are hosting other people's apps — customers, students, clients who do not trust each other — it is the most important thing to understand before you sell a single account. This post explains why, and what real multi-tenant isolation adds on top.
What "isolation" means, and Docker's actual boundary
Containers feel isolated: each has its own filesystem, its own process list, its own network view. That isolation is real and useful. But it is built on kernel features — namespaces and cgroups — and every container on a host shares one kernel. That shared kernel is the crux:
- A container escape is a full-host compromise. If a tenant breaks out of their container through a kernel vulnerability or a misconfiguration, they are not in another container — they are on the host, with reach into every other tenant's data. The shared kernel is a single, large attack surface that all tenants touch.
- Misconfiguration is easy and dangerous. A mounted Docker socket, a
--privilegedflag copied from a forum post, an over-broad bind mount — any of these quietly turns a container into a path to the host. In a multi-tenant setting, one careless template is a cross-customer breach. - Default resource sharing enables denial of service. Without enforced limits, one tenant can starve the rest of CPU, memory, or disk — availability is part of security, and unlimited containers break it.
Docker's own documentation and the security community are clear on this: containers are not a strong trust boundary for hostile, multi-tenant workloads on their own. They are excellent packaging and isolation for cooperating workloads.
The three ways to actually isolate tenants
If Docker alone is not enough, what is? There are three established approaches, and serious platforms use one or more:
Defense in depth: why layers beat any single wall
The principle behind option 3 is defense in depth. No single isolation mechanism is perfect; the goal is that a tenant who defeats one still faces others. This is exactly how Panelica isolates accounts, and containers deployed by an account inherit that isolation rather than running loose on the host. Every account sits behind multiple independent boundaries at once — a dedicated Unix user and group with its own file ownership, PID and mount namespaces that stop one account from seeing another's processes or filesystem, an SSH chroot for shell access, and a per-account cgroup v2 slice that caps total CPU, memory, I/O, and process count. A tenant's containers deploy inside that account's slice, so an escape from a single container still runs into the account's user boundary, its namespace boundary, and its resource ceiling. One failure is not a breach; several independent mechanisms would all have to fail together.
The resource slice deserves emphasis because availability is a security property too: because the account's total consumption is capped at the kernel level, one tenant's runaway or malicious container cannot starve the others. The kernel enforces it, not a monitoring script reacting after the damage is done. We go deeper on how these OS-level boundaries compare to older approaches in our write-up on CageFS versus namespaces and cgroup v2.
What this means for you, by situation
| Your situation | Is Docker alone enough? | What to do |
|---|---|---|
| Hosting your own apps | Generally yes | Follow container hardening basics; the tenants all trust each other (you) |
| A team of trusted colleagues | Mostly | Add resource limits and avoid privileged containers; low hostile-tenant risk |
| Customers who do not trust each other | No | Add per-tenant OS-level isolation, hardened runtimes, or per-tenant VMs |
| Untrusted, potentially hostile users | Definitely not | Strongest isolation available — per-tenant VMs or layered isolation, plus hardening |
Hardening you should do regardless
Even with strong tenant isolation, the container basics still matter:
- Never mount the Docker socket into a tenant-accessible container — it is root on the host.
- Avoid
--privilegedand drop unneeded capabilities; grant only what an app genuinely requires, declared openly. - Enforce resource limits on every container so no tenant can exhaust the host (how to set them).
- Keep the host kernel patched. Since the kernel is the shared boundary, its vulnerabilities are your tenant-isolation vulnerabilities.
- Prefer minimal, trusted images — less surface, fewer known vulnerabilities to inherit.
Frequently asked questions
So is Docker insecure?
No. Docker is secure for what it is designed for — isolating and packaging cooperating workloads. The mistake is assuming it is a strong boundary between mutually hostile tenants, which is a different and harder problem it was not built to solve alone.
Do I need VMs for every customer?
Not necessarily. Per-tenant VMs are the strongest and heaviest option. Layered OS-level isolation around containers is a strong, far denser middle ground suitable for most hosting scenarios; reserve per-tenant VMs for the highest-risk workloads.
What is the single most common multi-tenant mistake?
Exposing the Docker socket to a container, or running tenant containers privileged. Either hands a tenant an easy path to the host and therefore to every other tenant. Close those doors first.
How does Panelica handle this?
Containers deploy inside a per-account isolation boundary — dedicated Unix user, PID and mount namespaces, SSH chroot, and a cgroup v2 resource slice — so a tenant's containers are contained by several independent OS-level mechanisms, not by the container boundary alone.
The takeaway
Docker alone is not safe for multi-tenant hosting, and believing otherwise is a security failure waiting to happen — one shared kernel means one container escape reaches every tenant. The fix is layers: per-tenant VMs, hardened runtimes, or OS-level isolation wrapping each account so that defeating one boundary is not defeating all of them. If you host your own apps, carry on. If you host untrusted customers, make the isolation architecture — not the container — your trust boundary. That layered model is exactly what Panelica applies to every account, and to the containers those accounts run.