Infraestrutura & Cloud
Docker: o que é, como funciona e os principais conceitos de containers
Entenda o que é Docker, como funcionam containers, imagens, Dockerfile, volumes, redes e registries, e como esses componentes se encaixam no ciclo de desenvolvimento e infraestrutura.
Por Thiago Henrique ·
Aplicações modernas precisam ser executadas de forma previsível em diferentes ambientes.
Desenvolvimento.
Homologação.
CI/CD.
Cloud.
Servidores locais.
O problema é que uma aplicação raramente depende apenas do próprio código.
Ela pode precisar de uma versão específica de runtime, bibliotecas, pacotes, variáveis de ambiente, serviços auxiliares e configurações do sistema.
Quando essas dependências são instaladas diretamente em cada servidor ou estação, diferenças entre ambientes começam a aparecer.
É aí que containers entram.
E Docker se tornou uma das tecnologias mais conhecidas para construir, distribuir e executar aplicações em containers.
A documentação oficial do Docker descreve containers como instâncias executáveis de imagens e apresenta imagens, containers, redes e volumes como alguns dos principais objetos da plataforma.
Entender Docker, portanto, não é apenas aprender um comando como docker run.
É entender uma arquitetura.
Código → Dockerfile → imagem → registry → container → rede → armazenamento
Essa sequência ajuda a compreender quase todo o ciclo básico.
O que é Docker
Docker é uma plataforma para construir, distribuir e executar aplicações em containers.
Um container pode ser entendido como um processo isolado que executa uma aplicação com os arquivos e dependências necessários para seu funcionamento.
Na prática, isso permite empacotar uma aplicação junto com seu ambiente de execução de forma mais previsível.
Imagine uma API que depende de:
Python 3.13;
determinadas bibliotecas;
arquivos de configuração;
uma porta específica;
variáveis de ambiente.
Em vez de instalar tudo manualmente em cada servidor, é possível construir uma imagem contendo essas dependências.
A mesma imagem pode ser executada em diferentes ambientes compatíveis.
Isso reduz um problema clássico:
“na minha máquina funciona.”
Container não é máquina virtual
Containers e máquinas virtuais resolvem problemas diferentes.
Uma máquina virtual normalmente possui:
hardware virtual → sistema operacional completo → aplicações
Já vários containers podem compartilhar o kernel do host, mantendo isolamento entre processos.
De forma simplificada:
Máquinas virtuais
Host → Hypervisor → VM → Sistema Operacional → Aplicação
Containers
Host → Sistema Operacional → Container Runtime → Container → Aplicação
Isso faz com que containers normalmente tenham menor overhead e iniciem mais rapidamente que máquinas virtuais.
Mas isso não significa que containers substituam virtualização.
É muito comum executar containers dentro de máquinas virtuais em ambientes de produção.
Clouds públicas, clusters Kubernetes e plataformas gerenciadas frequentemente combinam as duas tecnologias.
Imagem e container não são a mesma coisa
Esse é um dos conceitos mais importantes de Docker.
Uma imagem é o pacote utilizado para criar containers.
Um container é uma instância em execução dessa imagem.
A documentação do Docker sobre imagens descreve uma imagem como um pacote padronizado contendo arquivos, binários, bibliotecas e configurações necessárias para executar um container.
Podemos pensar assim:
Imagem = modelo
Container = execução desse modelo
A mesma imagem pode originar vários containers.
Por exemplo:
imagem: nginx:1.29
pode gerar:
container-web-01 container-web-02 container-web-03
Todos partem da mesma imagem, mas possuem processos e estado de execução independentes.
Imagens são formadas por camadas
Imagens Docker são construídas em camadas.
Cada instrução relevante de um Dockerfile pode adicionar uma camada ao filesystem da imagem.
Por exemplo:
FROM node:22-alpine WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . CMD ["npm", "start"]
Nesse exemplo, a imagem começa a partir de uma imagem base do Node.js.
Depois recebe:
diretório de trabalho;
arquivos de dependências;
instalação de pacotes;
código da aplicação;
comando de inicialização.
A estrutura em camadas permite reutilização e cache.
Se apenas o código da aplicação mudar, algumas camadas anteriores podem continuar sendo reaproveitadas durante o build.
Isso torna a ordem das instruções no Dockerfile importante.
O papel do Dockerfile
O Dockerfile é um arquivo de texto que descreve como uma imagem deve ser construída.
A documentação oficial define o Dockerfile como o documento que fornece instruções ao builder sobre comandos, arquivos, configuração e processo de inicialização.
Algumas instruções comuns são:
FROM Define a imagem base.
WORKDIR Define o diretório de trabalho.
COPY Copia arquivos para a imagem.
RUN Executa comandos durante o build.
ENV Define variáveis de ambiente.
EXPOSE Documenta a porta utilizada pela aplicação.
USER Define o usuário utilizado pelo processo.
CMD Define o comando padrão do container.
Isso transforma o ambiente da aplicação em configuração versionável.
O Dockerfile pode ser mantido no Git junto com o código.
Dessa forma, mudanças na imagem passam pelo mesmo fluxo de versionamento e revisão.
Build transforma Dockerfile em imagem
Quando executamos um build, o Docker utiliza o Dockerfile e o contexto informado para gerar uma imagem.
O fluxo básico é:
Código + Dockerfile → Build → Imagem
A imagem recebe um identificador e normalmente uma tag.
Por exemplo:
minha-api:1.4.2
Tags ajudam a identificar versões.
É comum encontrar nomes como:
app:latest app:1.0 app:1.0.5 app:2026.09.27
Em ambientes controlados, versões explícitas são mais seguras que depender exclusivamente de latest, porque deixam claro qual artefato está sendo executado.
Registry é o repositório de imagens
Depois de construir uma imagem, é necessário distribuí-la.
É aí que entram os registries.
A documentação do Docker define registry como um local centralizado para armazenar e compartilhar imagens de containers.
Exemplos incluem:
Docker Hub;
Amazon ECR;
Azure Container Registry;
GitHub Container Registry;
GitLab Container Registry;
Harbor.
O fluxo passa a ser:
Código → Build → Imagem → Registry → Ambiente
Uma pipeline pode construir a imagem, executar verificações, adicionar uma tag e fazer push para um registry.
Depois, servidores ou clusters fazem pull dessa imagem para executá-la.
Container é uma instância executável
Quando uma imagem é executada, surge um container.
A documentação do Docker resume essa relação dizendo que um container é uma instância executável de uma imagem.
Durante a execução, o container possui:
processo;
filesystem gravável próprio;
interfaces de rede;
configuração;
variáveis de ambiente;
limites de recursos quando definidos.
Mas existe uma característica importante.
Containers devem ser tratados como descartáveis.
Se um container falhar, muitas arquiteturas preferem criar outro a tentar “consertar” manualmente o container existente.
Essa mentalidade é importante para automação e orquestração.
Containers são efêmeros, dados nem sempre
Por padrão, arquivos gravados na camada gravável do container estão associados àquele container.
Se ele for removido, esses dados podem desaparecer.
A documentação de storage do Docker destaca justamente que dados gravados apenas na writable layer não persistem após a destruição do container.
Por isso existem mecanismos de persistência.
Um dos principais são os volumes.
Volumes persistem dados fora do ciclo de vida do container
Volumes são áreas de armazenamento gerenciadas pelo Docker.
Segundo a documentação oficial de volumes, eles são mecanismos persistentes criados e gerenciados pelo Docker para armazenar dados utilizados pelos containers.
Imagine um banco de dados PostgreSQL executando em container.
O processo pode ser recriado.
Mas os dados não podem desaparecer toda vez que o container é substituído.
Então podemos ter:
Container PostgreSQL → Volume de dados
O container pode morrer.
Outro container pode ser criado.
O volume continua existindo.
Isso separa:
ciclo de vida da aplicação
de
ciclo de vida dos dados
Volumes e bind mounts são diferentes
Docker possui mais de uma forma de montar dados.
Volume
Gerenciado pelo Docker.
Bom para persistência de dados de aplicações.
Bind mount
Mapeia diretamente um caminho do host para dentro do container.
Por exemplo:
C:\projeto → /app
ou em Linux:
/home/projeto → /app
Bind mounts são muito utilizados em desenvolvimento porque permitem alterar arquivos no host e refletir as mudanças dentro do container.
Volumes tendem a oferecer maior abstração em relação à estrutura do host.
Containers precisam se comunicar
Poucas aplicações funcionam isoladamente.
Imagine:
Frontend → API → Banco
Cada componente pode estar em um container diferente.
Eles precisam se comunicar.
Docker possui recursos próprios de networking para isso.
A documentação de networking explica que containers podem se conectar entre si e também a serviços externos ao Docker.
Uma arquitetura simples poderia ser:
Internet ↓ Frontend ↓ API ↓ Banco
Cada componente pode possuir seu próprio container e participar de uma rede Docker.
Portas internas e externas não são a mesma coisa
Imagine uma aplicação escutando na porta 3000 dentro do container.
Isso não significa automaticamente que a porta 3000 esteja disponível externamente no host.
Podemos publicar:
Host:8080 → Container:3000
Assim:
usuário acessa porta 8080 do host
e o tráfego chega à:
porta 3000 do container
Essa separação permite controlar como serviços são expostos.
Também evita a necessidade de atribuir uma porta pública diferente diretamente dentro de cada aplicação.
Redes Docker ajudam a isolar serviços
É possível criar redes específicas para grupos de containers.
Por exemplo:
Internet ↓ Frontend ↓ Rede frontend ↓ API ↓ Rede backend ↓ Banco
O banco não precisa necessariamente estar exposto diretamente ao host ou à Internet.
Ele pode aceitar comunicação apenas a partir da rede interna utilizada pela API.
Essa segmentação melhora organização e reduz exposição desnecessária.
Mas rede de containers não elimina requisitos tradicionais de segurança.
Firewall, autenticação, TLS, gestão de secrets e políticas de acesso continuam importantes.
Docker Compose organiza aplicações com múltiplos containers
Quando uma aplicação possui vários componentes, iniciar cada container manualmente rapidamente se torna inconveniente.
Docker Compose permite declarar serviços em um arquivo YAML.
Por exemplo:
services: web: image: minha-app:1.0 ports: - "8080:3000" database: image: postgres:17 volumes: - db-data:/var/lib/postgresql/data volumes: db-data:
Esse arquivo descreve os componentes da aplicação.
Isso facilita iniciar ambientes formados por múltiplos containers de forma padronizada.
Compose é muito utilizado em desenvolvimento, testes, laboratórios e também em cenários de menor complexidade.
Docker e CI/CD trabalham muito bem juntos
Containerização combina naturalmente com pipelines.
Um fluxo pode ser:
Git → CI → testes → build da imagem → scanning → registry → deploy
O código entra no pipeline.
Os testes são executados.
A imagem é construída.
A imagem pode passar por verificações de segurança.
Depois recebe uma tag e é enviada ao registry.
O ambiente faz deploy exatamente daquele artefato.
Isso reduz diferenças entre:
o que foi testado
e
o que foi publicado
Esse conceito se conecta diretamente ao artigo sobre CI/CD e pipelines modernas.
Imutabilidade ajuda a tornar deploys previsíveis
Um princípio importante de containers é evitar alterações manuais depois que o artefato já foi construído.
Imagine que a imagem api:2.4.0 foi aprovada em homologação.
O ideal é promover essa mesma imagem para produção.
Não:
entrar no servidor e instalar mais um pacote manualmente.
Se algo precisar mudar, a imagem deve ser reconstruída.
Isso cria rastreabilidade.
Mudança no código → nova imagem → nova versão
Esse modelo combina bem com Git, CI/CD e Infrastructure as Code.
Segurança começa pela construção da imagem
Container não deve ser tratado automaticamente como ambiente seguro.
Algumas práticas importantes incluem:
utilizar imagens base confiáveis;
reduzir dependências desnecessárias;
evitar executar processos como root;
manter imagens atualizadas;
verificar vulnerabilidades;
proteger secrets;
controlar permissões;
assinar e rastrear artefatos quando necessário.
Imagens menores também ajudam a reduzir superfície de ataque.
Multi-stage builds são uma técnica comum para separar dependências de compilação do artefato final.
Assim, compiladores e ferramentas utilizadas durante o build não precisam permanecer na imagem de produção.
Docker não é orquestração de cluster
Docker resolve muito bem construção, distribuição e execução de containers.
Mas quando surgem dezenas ou centenas de containers distribuídos em vários servidores, aparecem outros problemas:
onde cada container deve executar?
como escalar automaticamente?
como recuperar workloads após falhas?
como atualizar sem indisponibilidade?
como distribuir tráfego?
como administrar configuração e secrets em escala?
Esse é o território dos orquestradores.
E é aí que Kubernetes entra.
Docker ajuda a entender a unidade básica:
container
Kubernetes trabalha na administração dessas cargas em escala.
Esse será o próximo passo natural da sequência.
O ciclo completo
Depois de conectar os conceitos, podemos representar o fluxo assim:
Desenvolvedor
↓
Código + Dockerfile
↓
Build
↓
Imagem versionada
↓
Registry
↓
Pull
↓
Container
↓
Rede + Volume
↓
Aplicação em execução
A partir desse ponto, CI/CD pode automatizar o processo e Kubernetes pode assumir a orquestração em ambientes distribuídos.
Docker é mais do que “empacotar aplicação”
O valor de Docker não está apenas em executar aplicações dentro de containers.
A tecnologia ajuda a criar uma unidade padronizada de distribuição.
Código, dependências e configuração de execução passam a fazer parte de um artefato reproduzível.
Isso melhora:
portabilidade;
consistência entre ambientes;
automação;
versionamento;
integração com CI/CD;
escalabilidade operacional.
Mas containers não eliminam a necessidade de infraestrutura.
Continuamos precisando de computação, rede, armazenamento, segurança, observabilidade e gestão operacional.
Docker muda principalmente como a aplicação é empacotada e executada sobre essa infraestrutura.
Conclusão
Docker introduz uma camada de abstração importante entre aplicação e infraestrutura.
O desenvolvedor ou equipe de plataforma deixa de depender tanto da configuração manual de cada host e passa a trabalhar com imagens versionadas e containers reproduzíveis.
Os principais conceitos se conectam:
Dockerfile descreve a construção.
Imagem representa o artefato.
Registry distribui esse artefato.
Container executa a imagem.
Volume preserva dados.
Rede conecta serviços.
CI/CD automatiza construção e entrega.
Com essa base, fica muito mais fácil compreender tecnologias de orquestração.
E é justamente aí que entra o próximo assunto:
Kubernetes: arquitetura, Pods, Deployments, Services e escalabilidade.
