- Process tree (via PID namespaces)
- Network stack (via network namespaces)
- Filesystem mounts (via mount namespaces)
- Resource controls (via cgroups)

- Early Docker used LXC under the hood.
- Around Docker v0.9.0 (circa 2014), Docker introduced
libcontainerand later theruncproject, which became the reference implementation of the OCI runtime. - Modern Docker typically uses
containerd+runcfor the low-level container runtime stack.
OCI stands for the Open Container Initiative. It defines open standards for container runtimes and image formats so different tools can interoperate.
Common container-related projects and roles
Why use Docker (and similar higher-level tools)?
Directly configuring kernel primitives (namespaces, cgroups, mounts) is possible but complex and error-prone. Docker and comparable tools wrap those low-level operations with:
- Declarative image formats (Dockerfiles / OCI images)
- Image registries for distribution
- Simple CLI and APIs for running and managing containers
- Integration with orchestration platforms like Kubernetes