O Que é um Container e Por Que Isso Mudou Tudo

[92] O Que é um Container e Por Que Isso Mudou Tudo

O que é um container e por que ele mudou a entrega de software: o problema real por trás do "funciona na minha máquina", namespaces e cgroups como base do isolamento, a comparação com máquinas virtuais, imagens em camadas e o papel do Docker na popularização da tecnologia.
DevOps

10 min de leitura

Durante décadas, o processo de colocar software em produção seguia um ritual previsível de imprevisibilidades. O desenvolvedor escrevia o código na sua máquina, que tinha uma versão específica do Python, uma versão específica de uma biblioteca, uma variável de ambiente configurada de um jeito particular. O código funcionava ali. Quando chegava ao servidor de produção — com outra versão do Python, outras bibliotecas, outras configurações — quebrava.

"Funciona na minha máquina" não era uma desculpa. Era um diagnóstico preciso de um problema estrutural: a ausência de um mecanismo que garantisse que o ambiente de execução fosse idêntico em qualquer lugar.

Máquinas virtuais resolviam parte do problema, mas ao custo de gigabytes de overhead por aplicação, minutos de inicialização e complexidade de gerenciamento. Era como transportar cada passageiro em um carro próprio quando um ônibus resolveria.

Os containers chegaram como o ônibus.

O Que é um Container

Um container é um processo isolado que carrega consigo tudo que precisa para executar: código, runtime, bibliotecas, variáveis de ambiente e configurações. Ele roda sobre o kernel do sistema operacional hospedeiro, mas enxerga apenas seus próprios recursos — não tem acesso ao sistema de arquivos do host, não vê os outros processos, tem sua própria interface de rede.

O isolamento é garantido por duas funcionalidades do kernel Linux:

Namespaces — criam visões isoladas de recursos do sistema. Um container tem seu próprio namespace de processos (não enxerga os processos do host), seu próprio namespace de rede (tem seu próprio IP), seu próprio namespace de sistema de arquivos.

cgroups (control groups) — limitam o quanto de CPU, memória e I/O um processo pode consumir. Um container não pode monopolizar os recursos da máquina hospedeira.

Container vs Máquina Virtual

A diferença fundamental está em onde o isolamento acontece:

┌─────────────────────────────────────┐
│         Máquina Virtual             │
│  ┌──────────┐  ┌──────────┐        │
│  │  App A   │  │  App B   │        │
│  │──────────│  │──────────│        │
│  │  Guest   │  │  Guest   │        │
│  │    OS    │  │    OS    │        │
│  └──────────┘  └──────────┘        │
│         Hypervisor                  │
│         Hardware                    │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│            Container                │
│  ┌──────────┐  ┌──────────┐        │
│  │  App A   │  │  App B   │        │
│  │──────────│  │──────────│        │
│  │  Libs A  │  │  Libs B  │        │
│  └──────────┘  └──────────┘        │
│         Container Runtime           │
│         Host OS Kernel              │
│         Hardware                    │
└─────────────────────────────────────┘

Uma máquina virtual precisa de um sistema operacional completo para cada instância — gigabytes de disco, centenas de megabytes de RAM só para o OS. Um container compartilha o kernel do host e carrega apenas o que a aplicação realmente precisa. O resultado: containers iniciam em segundos, ocupam megabytes, e é possível rodar dezenas deles onde antes cabiam poucos VMs.

Isso não significa que containers substituem máquinas virtuais em todos os casos. Em ambientes de nuvem, os próprios containers frequentemente rodam dentro de VMs — as camadas se complementam. O que mudou foi a unidade de trabalho para empacotamento e entrega de aplicações.

O Que é uma Imagem

Um container é uma instância em execução de uma imagem. A imagem é o template — imutável, versionável, compartilhável. O container é o processo vivo criado a partir desse template.

A analogia com orientação a objetos é precisa: a imagem é a classe, o container é o objeto instanciado a partir dela.

Uma imagem é construída em camadas. Cada instrução no Dockerfile — o arquivo que descreve como construir a imagem — cria uma camada. Camadas são imutáveis e reutilizáveis: se duas imagens diferentes partem da mesma camada base, essa camada é armazenada apenas uma vez no disco.

┌─────────────────────┐
│   Camada da App     │  ← seu código
├─────────────────────┤
│  Camada das Libs    │  ← dependências instaladas
├─────────────────────┤
│  Camada do Runtime  │  ← Node.js, Python, Java...
├─────────────────────┤
│  Camada Base do OS  │  ← ubuntu:22.04, alpine:3.19...
└─────────────────────┘

O Que é o Docker

Docker é a plataforma que popularizou os containers. Lançado em 2013, ele não inventou os containers — a tecnologia subjacente de namespaces e cgroups já existia no Linux há anos — mas criou uma experiência de usuário que tornou containers acessíveis para qualquer desenvolvedor.

O Docker é composto por:

Docker Engine — o daemon que roda em segundo plano, gerenciando containers, imagens, redes e volumes.

Docker CLI — a interface de linha de comando (docker) que o usuário usa para interagir com o daemon.

Docker Hub — o registro público de imagens. É o lugar onde imagens oficiais de Nginx, PostgreSQL, Redis, Node.js e milhares de outras ferramentas estão disponíveis gratuitamente.

Por Que Isso Mudou o DevOps

Antes dos containers, o processo de deploy envolvia configurar manualmente cada servidor de destino: instalar o runtime correto, configurar variáveis de ambiente, gerenciar conflitos entre aplicações que precisavam de versões diferentes da mesma dependência.

Com containers, o que vai para produção é a imagem — e a imagem já contém tudo. O servidor de produção não precisa saber nada sobre a aplicação além de como rodar um container. O pipeline de CI/CD constrói a imagem, a testa e a envia para um registro. O servidor de produção apenas a executa.

Essa separação de responsabilidades — construir uma vez, rodar em qualquer lugar — é o que tornou possível o deploy contínuo em escala, o desenvolvimento em microsserviços e, eventualmente, a orquestração com Kubernetes.

Nos próximos artigos, essa teoria se transforma em prática: instalação, primeiros containers, Dockerfiles e composição de serviços.

O Que Vem a Seguir

No próximo artigo a teoria cede lugar à prática: instalação do Docker, primeiros comandos, execução dos primeiros containers e entendimento do ciclo de vida de um container em execução.

Referências para Aprofundamento

Documentação oficial

Leitura técnica

Prática

  • Play with Docker — Ambiente Docker gratuito no navegador, sem instalação. Ideal para explorar antes de instalar localmente.
  • Docker Getting Started — docs.docker.com — Tutorial oficial do Docker, progressivo e bem estruturado. Complementa diretamente os próximos artigos da série.

Módulo 3 — Containers com Docker

Exercícios

Exercício 1

O artigo trata "funciona na minha máquina" como um diagnóstico preciso, e não como desculpa. Por quê? O que faltava estruturalmente?

Ver resposta

✓ Resposta: Porque a frase descreve com exatidão o que aconteceu: o código realmente funcionava naquela máquina, com aquela versão de runtime, aquelas bibliotecas e aquelas variáveis de ambiente. O problema nunca foi a competência de quem escreveu, e sim a ausência de um mecanismo que garantisse ambiente de execução idêntico em qualquer lugar. Enquanto o ambiente for remontado à mão em cada servidor, a divergência é apenas questão de tempo — e o container fecha essa lacuna transportando o ambiente junto com o código, em vez de tentar reproduzi-lo no destino.

Exercício 2

O que namespaces garantem e o que cgroups garantem? Um container sem cgroups ainda estaria isolado?

Ver resposta

✓ Resposta: Namespaces criam visões isoladas dos recursos do sistema: o container tem o próprio namespace de processos, de rede — com IP próprio — e de sistema de arquivos. Ou seja, ele não enxerga o resto da máquina. Os cgroups limitam quanto de CPU, memória e I/O aquele processo pode consumir: ele não monopoliza a máquina. São garantias diferentes, e a pergunta expõe isso: sem cgroups o container continuaria isolado quanto à visibilidade, mas um vazamento de memória dentro dele consumiria toda a RAM do host e derrubaria os demais containers junto. Isolamento de visão não é isolamento de recurso.

Exercício 3

Onde acontece o isolamento em uma máquina virtual e onde acontece em um container? Por que containers iniciam em segundos — e por que isso não significa que VMs ficaram obsoletas?

Ver resposta

✓ Resposta: Na VM o isolamento acontece no hypervisor, e cada instância carrega um sistema operacional convidado completo — gigabytes de disco e centenas de megabytes de RAM apenas para o OS, que ainda precisa inicializar. No container o isolamento acontece no kernel do host, que já está rodando; ele carrega apenas a aplicação e suas bibliotecas. Não há sistema operacional para dar boot, e é exatamente daí que vêm os segundos no lugar de minutos. Quanto à obsolescência, o artigo é explícito: em ambientes de nuvem os containers frequentemente rodam dentro de VMs, e as camadas se complementam. O que mudou foi a unidade de empacotamento e entrega da aplicação, não a camada de virtualização.

Exercício 4

Qual a diferença entre imagem e container? E por que camadas podem ser reutilizadas entre imagens diferentes?

Ver resposta

✓ Resposta: A imagem é o template — imutável, versionável e compartilhável. O container é o processo vivo criado a partir dela. Na analogia com orientação a objetos, a imagem é a classe e o container é o objeto instanciado; da mesma classe saem quantos objetos você quiser, e nenhum deles altera a classe. As camadas são reutilizáveis justamente porque são imutáveis: se duas imagens partem da mesma base — ubuntu:22.04, por exemplo — aquela camada é bit a bit idêntica nas duas e fica armazenada uma única vez em disco. É o que faz a segunda imagem de uma mesma família custar pouco para baixar, e o que dá sentido ao cache durante o build.

Exercício 5

O Docker não inventou os containers. O que ele efetivamente criou em 2013, e por que essa distinção importa?

Ver resposta

✓ Resposta: Namespaces e cgroups já existiam no kernel Linux havia anos. O que o Docker trouxe foi a experiência de uso: um formato de imagem, um CLI simples e o Docker Hub como registro público com milhares de imagens prontas. A distinção importa por dois motivos. Primeiro, ela separa capacidade técnica de adoção — a tecnologia existia e quase ninguém usava, porque montá-la à mão exigia especialista. Segundo, evita confundir a ferramenta com o padrão: a Open Container Initiative mantém os padrões abertos de formato de imagem e runtime, e o Docker é uma implementação deles, não a definição.

Exercício 6

O que "construir uma vez, rodar em qualquer lugar" muda na divisão de responsabilidades entre o pipeline de CI/CD e o servidor de produção?

Ver resposta

✓ Resposta: Antes, cada servidor de destino precisava ser preparado individualmente: instalar o runtime correto, configurar variáveis de ambiente e resolver conflitos entre aplicações que exigiam versões diferentes da mesma dependência. Com containers, o que vai para produção é a imagem — e ela já contém tudo. O pipeline passa a ser responsável por construir, testar e publicar essa imagem em um registro; o servidor de produção só precisa saber executar um container, sem saber absolutamente nada sobre a aplicação que roda dentro dele. É essa separação de responsabilidades que tornou viável o deploy contínuo em escala, a arquitetura de microsserviços e, depois, a orquestração com Kubernetes.

Comentários

Mais em DevOps

Introdução ao Terraform: Infraestrutura que Você Pode Versionar
Introdução ao Terraform: Infraestrutura que Você Pode Versionar

O problema dos snowflake servers e a infraestrutura que se pode versionar: o…

AWS na Prática: EC2, VPC e IAM em Profundidade
AWS na Prática: EC2, VPC e IAM em Profundidade

Os três serviços mais fundamentais da AWS em profundidade: famílias de…

ECS e Lambda: Containers e Serverless na AWS
ECS e Lambda: Containers e Serverless na AWS

Os serviços gerenciados de computação da AWS e seus trade-offs: os conceitos…