Olá! Bem-vindo ao nosso curso. Estou animado para começarmos essa jornada para aprofundar seus conhecimentos em Docker e tecnologias de nuvem.
Com sua vasta experiência em desenvolvimento de software e engenharia, sei que você valoriza entender "como as coisas funcionam" em vez de apenas seguir receitas. Por isso, nosso ponto de partida não será diretamente nos comandos do Docker, mas sim nos fundamentos que tornam os contêineres possíveis.
Nesta primeira lição, vamos desmistificar a mágica por trás da containerização. O objetivo é que, ao final, você consiga explicar com clareza a diferença entre virtualização e containerização, focando em como os contêineres compartilham o kernel do sistema operacional do hospedeiro e, ainda assim, conseguem isolar seus recursos. Este é o alicerce para todo o conhecimento que construiremos a seguir.
Virtualização vs. Containerização: Uma Visão Geral
Para começar, vamos estabelecer a diferença fundamental entre as duas tecnologias. Em um nível alto, pense em Máquinas Virtuais (VMs) como casas completas e independentes, cada uma com sua própria fundação, estrutura e sistemas (água, eletricidade). Contêineres, por outro lado, são como apartamentos em um mesmo prédio: eles compartilham a fundação e a estrutura principal do prédio, mas cada um tem seu próprio espaço interno isolado.
A imagem a seguir ilustra essa diferença arquitetural.

Como o diagrama mostra, a principal distinção é:
-
Máquinas Virtuais (VMs): Um Hypervisor (como VMware ou VirtualBox) emula componentes de hardware (CPU, RAM, disco). Sobre esse hardware virtual, você instala um sistema operacional completo (o "Guest OS"). Isso resulta em um isolamento forte, mas com um custo significativo em termos de recursos, tamanho em disco (gigabytes) e tempo de inicialização (minutos).
-
Contêineres: Em vez de virtualizar o hardware, a containerização virtualiza o próprio sistema operacional. Todos os contêineres compartilham o mesmo kernel do sistema operacional do hospedeiro (Host OS). Isso os torna extremamente leves (megabytes), rápidos para iniciar (segundos ou até milissegundos) e com desempenho próximo ao nativo, pois não há camada de emulação de hardware.
Mas se eles compartilham o mesmo kernel, como é possível que um contêiner não interfira no outro? A resposta está em alguns recursos inteligentes do kernel do Linux.
Os Pilares da Containerização: Namespaces e Cgroups
A "mágica" dos contêineres não vem de uma única tecnologia chamada "contêiner", mas da combinação de dois recursos fundamentais do kernel do Linux: Namespaces e Control Groups (cgroups).
Para obter uma visão geral abrangente de como esses recursos funcionam juntos, vamos começar com um artigo que detalha esses componentes principais.
📦 How Containers work? Deep dive into Containerization.
Para obter uma visão geral abrangente de como os contêineres são construídos a partir de recursos fundamentais do Linux, vamos começar com este artigo do The Cloud Handbook. Ele divide claramente os componentes principais.
Por favor, leia a introdução e as seções 'What is namespaces and what does it have to do with containers?' e 'What is cgroups?'. Foque em entender o propósito de cada tecnologia: namespaces para isolamento e cgroups para limitação de recursos. Você pode passar rapidamente pela parte com o comando strace por enquanto, pois exploraremos isso com mais detalhes em um vídeo a seguir.
Como o artigo explicou, esses dois mecanismos têm papéis distintos e complementares:
- Namespaces: Controlam o que um processo pode ver.
- Cgroups: Controlam o que um processo pode usar.
Vamos aprofundar em cada um deles.
1. Isolamento com Namespaces
Os namespaces são a chave para o isolamento. Eles criam uma "bolha" em torno de um processo, dando-lhe a ilusão de que tem seu próprio ambiente exclusivo. Um processo dentro de um namespace não consegue "ver" ou interagir com processos, redes ou arquivos fora de sua bolha.
O vídeo a seguir demonstra de forma prática como os namespaces funcionam, usando ferramentas de linha de comando que serão familiares para você. É uma excelente maneira de ver esses conceitos em ação.
How Docker Works - Intro to Namespaces
O artigo nos deu uma base teórica sólida. Agora, vamos ver esses conceitos em ação. Este vídeo do canal LiveOverflow faz um excelente trabalho ao demonstrar como os namespaces funcionam usando ferramentas como pstree e strace, mostrando o que realmente acontece quando um contêiner é iniciado.
Assista ao vídeo do início até 09:20 e, em seguida, de 09:20 até o final (12:35). Preste muita atenção em: Como um processo em execução dentro de um contêiner também é visível no hospedeiro, mas com um PID (Process ID) diferente. O papel da chamada de sistema (syscall) unshare na criação de novos namespaces. A explicação dos namespaces PID, mount e network e como eles criam um ambiente isolado.
Para consolidar, aqui estão os principais tipos de namespaces que o Docker utiliza:
| Namespace | Propósito do Isolamento |
|---|---|
| PID | Isola os IDs de processo. Um contêiner não pode ver os processos do hospedeiro ou de outros contêineres. O primeiro processo dentro do contêiner se torna o "PID 1". |
| NET | Fornece ao contêiner sua própria pilha de rede (interfaces, endereços IP, tabelas de roteamento, portas). |
| MNT | Isola os pontos de montagem do sistema de arquivos. Cada contêiner tem sua própria raiz (/) e não pode acessar arquivos do hospedeiro. |
| UTS | Permite que cada contêiner tenha seu próprio hostname e nome de domínio. |
| IPC | Isola os recursos de comunicação entre processos (IPC), como memória compartilhada. |
| User | Mapeia os IDs de usuário. Um usuário root (UID 0) dentro de um contêiner pode ser um usuário não privilegiado no hospedeiro, aumentando a segurança. |
Teste seu entendimento!
Imagine que você executa dois contêineres de servidor web no mesmo host, e ambos estão configurados para escutar na porta 80. Por que eles não entram em conflito? Qual recurso do kernel é responsável por isso e como ele funciona?
Show answer
Eles não entram em conflito por causa do namespace de Rede (NET).
Cada contêiner obtém sua própria pilha de rede isolada. Isso significa que a "porta 80" dentro do contêiner A é um recurso completamente separado da "porta 80" dentro do contêiner B. Embora ambas as aplicações pensem que estão usando a porta 80, elas estão fazendo isso em seus próprios namespaces de rede. Para que o tráfego externo chegue a eles, o Docker mapeia portas do host para as portas específicas desses namespaces de rede (um tópico que veremos em detalhes mais adiante).
2. Limitação de Recursos com Cgroups
Se os namespaces criam os "apartamentos" isolados, os Control Groups (cgroups) funcionam como os medidores de utilidades, definindo quanta eletricidade (CPU), água (memória) e espaço (I/O de disco) cada apartamento pode usar.
Conforme visto no artigo, você pode instruir o Docker a limitar os recursos de um contêiner. Por exemplo:
docker run --memory=512m --cpus="0.5" nginx
Este comando diz ao kernel, através dos cgroups, para garantir que o contêiner nginx:
- Não use mais do que 512 megabytes de memória RAM.
- Não use mais do que 50% de um único núcleo de CPU.
Se o contêiner tentar exceder esses limites, o kernel intervirá. No caso da memória, ele pode encerrar o processo (Out Of Memory Killer); no caso da CPU, ele simplesmente não alocará mais tempo de processamento para ele. Isso é crucial para evitar que um único contêiner "faminto" por recursos afete o desempenho de outros contêineres ou do próprio sistema hospedeiro.
3. O Sistema de Arquivos Isolado
Finalmente, um contêiner precisa de seu próprio sistema de arquivos. Isso é alcançado usando uma operação chamada chroot (ou a mais moderna pivot_root). Ela essencialmente "prende" o processo do contêiner em um diretório específico, fazendo com que esse diretório pareça ser a raiz (/) do sistema para o processo. Isso impede que a aplicação dentro do contêiner navegue e acesse arquivos no sistema de arquivos do hospedeiro.
A forma como esses sistemas de arquivos são construídos em camadas eficientes é um tópico para nossa próxima lição sobre imagens Docker, mas por enquanto, o conceito-chave é o isolamento do ponto de vista do sistema de arquivos.
Conclusão
Nesta lição, estabelecemos as bases conceituais da containerização. Espero que a distinção entre virtualização e o funcionamento interno dos contêineres esteja mais clara.
Principais pontos a reter:
- VMs vs. Contêineres: VMs virtualizam o hardware e exigem um sistema operacional convidado completo. Contêineres virtualizam o sistema operacional e compartilham o kernel do hospedeiro, tornando-os muito mais leves e rápidos.
- Isolamento (o que se vê): É realizado pelos Namespaces do kernel do Linux, que criam uma visão isolada dos processos, rede, sistema de arquivos e outros recursos do sistema.
- Limitação (o que se usa): É imposta pelos Control Groups (cgroups), que limitam e monitoram o uso de recursos como CPU, memória e I/O.
- A verdade sobre os contêineres: Um contêiner não é uma "coisa" mágica, mas sim um processo Linux padrão que é "enjaulado" e restrito por esses recursos do kernel.
No próximo módulo, vamos subir um nível de abstração. Agora que entendemos os mecanismos de baixo nível, exploraremos a arquitetura do Docker—o Docker Engine, containerd e runc—e veremos como essas ferramentas orquestram os namespaces e cgroups para gerenciar o ciclo de vida dos contêineres de forma prática e eficiente.