Skip to content

Containers (Docker)

Máquinas virtuais x Containers

Definição: Máquina Virtual (VM)

Permite executar sistemas operacionais completos de forma isolada, garantindo segurança e compatibilidade entre ambientes diferentes — cada VM roda seu próprio Guest OS completo sobre um hypervisor. Exige mais recursos (cada VM precisa de um SO inteiro) e tem inicialização lenta (minutos).

Definição: Container

Alternativa mais leve e rápida às VMs: compartilha o kernel do sistema hospedeiro, isolando apenas processos e dependências — sem precisar de um sistema operacional Guest completo por unidade. Ideais para microsserviços, pipelines de CI/CD e aplicações que precisam escalar rapidamente, além de oferecerem portabilidade e fácil replicação.

Característica Máquinas virtuais (VMs) Containers
Isolamento Completo, com sistema operacional próprio Compartilham o kernel do host, isolamento a nível de processo
Desempenho Maior sobrecarga devido à virtualização Mais leves e rápidos para iniciar
Consumo de recursos Alto (cada VM precisa de um SO completo) Baixo (apenas a aplicação e suas dependências)
Portabilidade Portáveis, mas mais pesados para mover Altamente portáveis e fáceis de replicar
Tempo de inicialização Lento (minutos) Rápido (segundos)
Persistência de dados Persistente por padrão Necessário configurar volumes de persistência
Uso ideal Ambientes que exigem isolamento total ou SOs diferentes Microsserviços, pipelines de CI/CD, aplicações escaláveis

Definição: Quando escolher cada abordagem

VMs são recomendadas quando há necessidade de isolamento total, ou execução de sistemas operacionais diferentes entre si. Containers oferecem maior agilidade no desenvolvimento e na implantação. A escolha depende do contexto: nível de isolamento necessário e objetivos de escalabilidade.

Por baixo dos panos: namespaces, cgroups e LXC

Todo tipo de virtualização trata de dividir recursos e isolar os inquilinos (tenants).

  • Virtualização completa: o hypervisor emula uma máquina (BIOS, drivers, memória). Os guests podem ser PV (paravirtualização: o guest conhece o host e usa o kernel para acessar dispositivos, com boa performance) ou HVM (extensões de hardware e camadas de software, como o QEMU, emulam os dispositivos).
  • Virtualização em nível de sistema operacional (contêineres): isolam mais de uma instância de user space sobre o mesmo kernel. No Linux, o isolamento vem dos namespaces (cada contêiner vê só os seus processos, rede, sistema de arquivos, usuários) e o controle de consumo vem dos cgroups (control groups).

Definição: cgroups

Recurso do kernel Linux que agrupa processos e limita/contabiliza CPU, memória, E/S e rede. Ao passar do limite de memória do grupo, o kernel tenta recuperar memória e, em último caso, o OOM Killer mata o maior processo do grupo — é o que acontece com um contêiner que excede o seu limite. Os cgroups também servem fora de contêineres.

  • Um contêiner não é uma VM completa: é um sistema de arquivos raiz (root filesystem) mais processos isolados; não carrega kernel nem drivers. Por isso inicia em segundos e sobrecarrega muito menos. O LXC é o conjunto de ferramentas para manipular contêineres diretamente (lxc-create, lxc-start, lxc-console); do host se veem os processos do contêiner, mas de dentro dele só o que o isolamento permite. Docker, Kubernetes e Mesos constroem sobre esses mesmos princípios.
  • VMs e contêineres não se anulam: dividem recursos de formas complementares.

Camadas e princípios do Docker: cada instrução do Dockerfile (FROM, RUN, ADD/COPY, CMD) gera uma camada do sistema de arquivos da imagem, reutilizável e versionada em repositórios; as imagens só contêm arquivos. A convenção é um processo por contêiner (sem SSH): contêineres pequenos se compõem em arquiteturas maiores (composability), orquestrados por Compose/Kubernetes. Portas: -p porta_do_host:porta_do_container; docker run -d executa em segundo plano; docker ps, docker inspect, docker kill.

Docker

Definição: Docker

Ferramenta principal para criação e gerenciamento de containers, usando imagens compostas por camadas reutilizáveis, armazenadas em repositórios remotos (registries).

docker run -p 8080:80 nginx

Definição: docker run -p host:container imagem

Executa um container a partir de uma imagem, expondo uma porta do container para o host — no exemplo, quem acessa http://localhost:8080 no host chega à porta 80 dentro do container rodando Nginx. Outros exemplos comuns: bancos de dados (docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=senha -d -p 3306:3306 mysql) ou um cache Redis (docker run -d -p 6379:6379 redis) — o Docker elimina a necessidade de instalar esses softwares diretamente no sistema operacional.

Definição: Docker Hub

Repositório central (registry) onde é possível encontrar e compartilhar imagens de containers — o equivalente, para imagens Docker, de um repositório de código-fonte. Permite buscar imagens oficiais e compartilhadas pela comunidade, publicar imagens próprias, e integrar com pipelines de CI/CD.

Docker Compose

Definição: Docker Compose

Ferramenta que permite definir e coordenar, de maneira simplificada, todas as etapas necessárias para a execução de uma ou mais aplicações Docker — configurando todos os serviços, dependências e configurações num único arquivo YAML (docker-compose.yaml), facilitando o gerenciamento e a automação do ciclo de vida da aplicação.

version: '3.8'
services:
  web:
    image: nginx
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
  db:
    image: postgres
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:
  • version: define a versão da especificação do Docker Compose usada.
  • services: define os containers que farão parte da aplicação.
  • image: define a imagem Docker que será utilizada.
  • ports: mapeia as portas entre o host e o container.
  • volumes: mapeia os diretórios para persistência de dados.
  • environment: define as variáveis de ambiente para o container.
Comando Descrição
docker-compose up Inicia todos os serviços definidos no arquivo docker-compose.yaml
docker-compose stop Para todos os serviços
docker-compose down Para e remove todos os serviços, redes e volumes criados
docker-compose ps Lista todos os containers gerenciados pelo Docker Compose
docker-compose logs Exibe logs de todos os serviços
docker-compose build Constrói ou reconstrói os serviços
docker-compose exec nome_servico comando Executa um comando dentro de um container gerenciado pelo serviço definido

Rede entre containers

Definição: Containers são isolados uns dos outros por padrão

Por padrão, o Docker executa cada container em redes isoladas e independentes entre si — mesmo dois containers rodando na mesma máquina host não conseguem se comunicar diretamente usando localhost, porque cada um entende localhost como o próprio container que fez a requisição, não o host nem outros containers.

# 1. Criar uma rede
docker network create minha-rede

# 2. Executar os containers na mesma rede
docker run --network minha-rede --publish 8280:8280 --detach --name echoservice echoservice:1.0
docker run --network minha-rede --publish 8180:8180 --detach --name callerservice callerservice:1.0

Definição: Comunicação entre containers pelo nome

Colocar dois ou mais containers na mesma rede Docker permite que eles se comuniquem entre si usando o nome do container como hostname, em vez de localhost ou um IP fixo — um callerservice configurado para chamar http://echoservice:8280/echo (usando o nome do outro container) funciona corretamente dentro da rede, mesmo que http://localhost:8280/echo não funcionasse. No Docker Compose, todos os serviços de um mesmo arquivo docker-compose.yaml compartilham automaticamente a mesma rede, então essa comunicação por nome já funciona pronta, sem precisar criar a rede manualmente.

Kubernetes

Docker Compose resolve bem o desenvolvimento local, mas levanta questões novas em produção: o que acontece se a máquina cair? Como garantir que os serviços mais acessados tenham mais réplicas rodando, balanceando a carga entre elas? Como conseguir deploys isolados por aplicação, escalar automaticamente com base em métricas, ou substituir uma versão por outra gradualmente, sem indisponibilidade?

Definição: Kubernetes (K8s)

Plataforma open source para orquestração de containers, projetada para automatizar a implantação, o dimensionamento, a gestão e a operação de aplicações em escala — coordenando centenas ou milhares de containers de forma resiliente e escalável. Originalmente desenvolvido pelo Google (inspirado no sistema interno Borg), foi doado publicamente em 2014 à Cloud Native Computing Foundation (CNCF). Adotado por todos os grandes provedores de nuvem (Amazon EKS, Google GKE, Microsoft AKS), oferecendo portabilidade entre eles e evitando vendor lock-in.

Definição: Componentes principais do Kubernetes

O cluster é composto por um nó mestre (control plane) e múltiplos nós de trabalho (worker nodes): o mestre gerencia o estado desejado do sistema, decidindo onde e como os containers devem ser executados; os nós de trabalho hospedam os containers de fato. O Pod é a menor unidade de implantação — geralmente encapsula um ou mais containers com recursos e rede compartilhados. Por meio de objetos declarativos como Deployments, Services, ConfigMaps, Secrets, Volumes e Ingresses, é possível definir o comportamento desejado da aplicação e deixar que o Kubernetes tome as decisões necessárias para manter esse estado.

Definição: Self-healing

Um dos grandes diferenciais do Kubernetes: ele monitora constantemente o estado das aplicações e toma ações corretivas automáticas quando necessário — reiniciar containers falhos, mover pods para outros nós em caso de falha de hardware, ou escalar aplicações com base em métricas definidas — sem intervenção manual.

Recurso / Benefício Kubernetes Docker Compose
Escalabilidade horizontal automática Permite self-scaling baseado em métricas de CPU, memória e métricas customizadas Não possui suporte nativo para self-scaling
Alta disponibilidade (HA) Distribui pods em múltiplos nós, garantindo continuidade mesmo com falhas de máquinas Limitado a um único host, sem HA nativo
Self-healing Reinicia ou reprograma containers automaticamente em caso de falhas Não possui self-healing por padrão
Deploys e rollbacks com estratégia Suporta rolling updates e rollbacks controlados Apenas substitui containers, sem controle de versão de deploy
Service discovery e load balancing DNS interno e balanceamento de carga automático entre réplicas Requer configuração manual ou ferramentas externas
Observabilidade integrada Integra-se facilmente com Prometheus, Grafana, Loki, Tempo e outros Não possui controle de acesso nativo
Segurança e controle de acesso (RBAC) Controle de permissões por usuário, namespace ou recurso Sem suporte a RBAC
Gerenciamento declarativo via YAML Configuração como código para facilitar CI/CD e versionamento Tem suporte a YAML, mas com menos granularidade e recursos limitados
Orquestração em múltiplas máquinas Gerencia aplicações em clusters com múltiplos nós Limitado a um único host (Swarm está obsoleto)
Compatibilidade com cloud e híbrido Suporte nativo para GKE, EKS, AKS, OpenShift e outros provedores Não é usado em ambientes cloud-native empresariais

Definição: Extensibilidade e CRDs

Outro ponto forte do Kubernetes é sua extensibilidade: suporta plugins e integrações com sistemas de monitoramento, segurança, autenticação, redes e storage, além de permitir a criação de CRDs (Custom Resource Definitions) para adaptar o cluster a casos de uso específicos — um marco na consolidação do conceito de infraestrutura como código (IaC) e no movimento cloud-native.

Definição: Minikube — Kubernetes local

Para estudo e desenvolvimento local, o Minikube é um emulador que permite instalar e rodar um cluster Kubernetes de nó único na própria máquina, sem exigir acesso a um provedor de nuvem.