O problema
Você passou os últimos 4 capítulos montando componentes de um container na mão: unshare, cgroups, mount overlay, chroot. Funciona, mas ninguém quer digitar isso pra subir um WordPress.
O Docker apareceu em 2013 pra resolver exatamente isso. Ele não inventou namespaces, cgroups nem overlay. Só empacotou tudo com uma API limpa. Em vez de 5 comandos com sudo, você digita docker run nginx.
O que o Docker faz
Quando você executa docker run alpine echo ok, o Docker:
- Baixa a imagem (se não tiver em cache): layers da imagem Alpine
- Cria um overlay: lowerdir = layers da imagem, upperdir = container layer vazia
- Cria namespaces:
unshare --pid --net --mount --uts --ipc --cgroup - Cria cgroups: limites de CPU/RAM que você passou (
--memory,--cpus) - Configura rede: cria um par veth (uma ponta no container, outra na bridge
docker0) - Executa o comando:
chrootno overlay merged e executa o que você pediu
Tudo que a gente fez nos capítulos anteriores, mas automatizado.
Mão na massa
Subir um container e inspecionar
docker run -d --name demo alpine:3.23 sleep infinity
080d112e5a06d4d185902a77aea0cd3f3e8847560bc860a269109f08a194d73bQual o PID real do container no host?
docker inspect demo --format '{{.State.Pid}}'61566Quais namespaces ele está usando?
sudo lsns -p $(docker inspect demo --format '{{.State.Pid}}') NS TYPE NPROCS PID USER COMMAND
4026531834 time 125 1 root /sbin/init
4026531837 user 125 1 root /sbin/init
4026532376 mnt 1 61566 root sleep infinity
4026532377 uts 1 61566 root sleep infinity
4026532378 ipc 1 61566 root sleep infinity
4026532379 pid 1 61566 root sleep infinity
4026532380 cgroup 1 61566 root sleep infinity
4026532381 net 1 61566 root sleep infinity5 namespaces isolados (mnt, uts, ipc, pid, net) mais o cgroup. O sleep infinity é só mais um processo no host, mas com namespaces próprios. As entradas com PID 1 (time, user) são os namespaces raiz do sistema. Todo processo pertence a eles também.
Limites de recursos
docker run -d --name limited --memory 128m --cpus 0.5 alpine:3.23 sleep infinity
O Docker converteu --memory 128m em cgroup. Confere:
echo $(< /sys/fs/cgroup/system.slice/docker-$(docker inspect limited --format '{{.Id}}').scope/memory.max)134217728128 × 1024 × 1024 = 134217728 bytes. O Docker escreveu isso no cgroup, o mesmo princípio de quando usamos o systemd para essa limitação.
Camadas da imagem
docker image inspect alpine:3.23 --format '{{.RootFS.Layers}}'[sha256:29df493baa13de438d6d2ece3a8333032e0b7b9b9d8cce4ee82194da255f61e1]Cada hash é uma camada. O Docker monta todas como lowerdir do overlay.
Rede
docker run -d --name web nginx:alpine
docker inspect web --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'172.17.0.5O Docker criou um par veth: uma ponta no container, outra no host. O container tem IP na rede bridge docker0.
No próximo capítulo: Dockerfile. Como criar suas próprias imagens.