Network namespaces give each container or sandbox its own private network stack. Step through creating one, connecting it to the host with a veth pair, and bringing it up — and see exactly which ip command does each part.
This is the actual mechanism containers are built on. When you run docker run, Docker (via runc) does almost exactly what this page walks through: create a namespace, create a veth pair, move one end in, assign addresses, and bring interfaces up. Namespaces handle isolation; a separate kernel feature called cgroups handles resource limits. Together they're most of what "container" means at the kernel level — no VM required.
ip command reference| Command | What it does |
|---|---|
| ip netns add <name> | Creates a new, isolated network namespace. |
| ip netns list | Lists all named namespaces on the system. |
| ip netns exec <name> <cmd> | Runs any command inside that namespace's network context — the rest of the system (filesystem, processes) is unaffected. |
| ip link add <a> type veth peer name <b> | Creates a connected veth pair, interfaces a and b. |
| ip link set <iface> netns <name> | Moves an interface into a namespace — it disappears from the current namespace's ip link output entirely. |
| ip addr add <ip>/<prefix> dev <iface> | Assigns an IP address (see the subnetting page for what the prefix means) to an interface. |
| ip link set <iface> up | Activates an interface — until this runs, it can't send or receive anything. |
lo, which is up from boot, every new namespace starts with lo down — step 9 above exists for a reason, and forgetting it is one of the most common namespace debugging headaches./var/run/netns/ keeps it alive (and referenceable by name) even with no running process — that's what makes ip netns add persistent instead of disappearing the instant you stop using it.