Namespaces from first principles
Build a container by hand with unshare — no Docker.
There is no such thing as a container in the Linux kernel — there is a process, wrapped in namespaces and constrained by cgroups. The fastest way to internalize that is to build one by hand with unshare, no Docker involved. Once you have created a private PID, mount, and network view for an ordinary /bin/sh, the mystique evaporates and, crucially, so does any illusion that the boundary is thick.
# a "container" with its own PID, mount, UTS, and network namespace — no Docker$ sudo unshare --pid --mount --uts --net --fork --mount-proc /bin/sh# inside:# ps -ef <- only our own processes; sh is PID 1# hostname box <- our own hostname, host unaffected# ip addr <- an empty network namespace (just lo, down)
One namespace per resource
Each namespace type virtualizes exactly one global resource. PID gives a process its own process-number space with its own PID 1. MNT gives it a private mount table. NET gives it its own interfaces, routes, and ports. UTS isolates the hostname; IPC isolates shared memory and semaphores; and USER — the one that matters most for security — maps user and group IDs, so root inside can be an unprivileged UID outside. Docker simply creates all of these at once and pivots into a prepared root filesystem.
Namespaces are the visibility half only
A namespace controls what a process can see, not what it can do to what it sees. A process in its own mount namespace still runs with whatever capabilities and UID it was given, against the same kernel. That is why namespaces alone are not a security boundary — they must be paired with capabilities, seccomp, and (ideally) a user namespace. Sharing a namespace with the host deliberately removes even the visibility barrier.
# entering a running container’s namespaces from the host (how nsenter/docker exec work)$ pid=$(docker inspect -f '{{.State.Pid}}' web)$ sudo nsenter -t "$pid" -m -u -n -p -- ps -ef # we are now "inside" web# the container is just PID $pid on the host wearing five namespaces