Docker: O Guia Definitivo
Acabe com o "na minha máquina funciona". Aprenda a criar, distribuir e escalar aplicações em containers como um Engenheiro DevOps.
1. Introdução: O Fim do "Na minha máquina funciona"
Todo desenvolvedor já passou por isso: você passa semanas codando, tudo funciona perfeitamente no seu notebook. Mas, quando envia para o servidor de produção, tudo quebra.
O motivo? "Dependency Hell" (Inferno de Dependências). Talvez o servidor tenha uma versão diferente do Node.js, ou o banco de dados tenha uma configuração de permissão distinta.
O Docker resolveu isso criando o conceito de Containerização. Ele não envia apenas o seu código; ele envia o ambiente inteiro (o sistema operacional, as bibliotecas, as configurações e o código) dentro de uma caixa lacrada. Se essa caixa abre no seu notebook, ela abrirá exatamente igual em qualquer servidor do mundo.
2. VM vs. Containers: A Batalha da Arquitetura
Para entender por que o Docker é tão rápido, você precisa entender o que veio antes dele: as Máquinas Virtuais (VMs).
A Analogia da Moradia
Imagine que você precisa hospedar 3 famílias (3 aplicações):
- Máquina Virtual (Casas Separadas): Cada família constrói sua própria casa, com sua própria fundação, encanamento e rede elétrica, mesmo que morem no mesmo terreno. Isso gasta muito material (recursos) e demora para construir.
- Container (Apartamentos): Você constrói um único prédio com uma fundação robusta (o Kernel do Host). Cada família tem seu apartamento privado (isolamento), mas todos compartilham a mesma água e luz do prédio. É muito mais eficiente.
A Explicação Técnica (Hypervisor vs Kernel)
A mágica acontece no nível do Sistema Operacional:
- VMs (VirtualBox, VMware): Usam um Hypervisor para emular hardware falso. Cada VM precisa carregar um Sistema Operacional completo (ex: Windows ou Linux inteiro) para rodar uma simples calculadora. Isso consome Gigabytes de RAM.
- Containers (Docker): Compartilham o Kernel (o núcleo) do sistema operacional da máquina hospedeira. O container carrega apenas o estritamente necessário para a aplicação rodar. Por isso, ele liga em milissegundos.
| Característica | Máquina Virtual (VM) | Docker Container |
|---|---|---|
| O que carrega? | Um SO completo + Hardware Virtual. | Apenas os binários da aplicação. |
| Peso (Tamanho) | Pesado (Gigabytes). | Leve (Megabytes). |
| Tempo de Boot | Lento (Minutos para ligar o SO). | Instantâneo (Milissegundos). |
| Desempenho | Menor (perda na emulação). | Nativo (roda direto no processador). |
3. Preparando o Terreno: Como Instalar o Docker
O Docker roda em qualquer lugar, mas a instalação varia conforme o seu sistema. O padrão da indústria hoje é utilizar o Docker Desktop.
Passo 1: Instalação
🪟 Para Windows (Atenção aqui!)
O Windows moderno usa o WSL 2 (Windows Subsystem for Linux). Isso permite rodar o Docker com performance nativa de Linux.
- Baixe o instalador no site oficial: Docker Desktop for Windows.
- Durante a instalação, certifique-se de marcar a opção: "Use WSL 2 instead of Hyper-V".
-
Após instalar, abra o PowerShell e digite
wsl --updatepara garantir que o kernel do Linux está atualizado.
🍎 Para Mac (Apple Silicon ou Intel)
- Se você usa chip M1/M2/M3, baixe a versão "Apple Silicon".
- Se usa Macs antigos, baixe a versão "Intel Chip".
- Arraste para a pasta Applications e dê as permissões de segurança solicitadas.
🐧 Para Linux (Ubuntu/Debian)
No Linux, geralmente usamos o terminal direto, sem interface gráfica (embora o Docker Desktop também exista para Linux).
# 1. Atualize os pacotes
sudo apt-get update
# 2. Instale o Docker
sudo apt-get install docker.io
# 3. Dica Pro: Rode o Docker sem precisar de 'sudo' toda vez
sudo usermod -aG docker $USER
Passo 2: Verificando se funcionou
Abra seu terminal (CMD, PowerShell ou Terminal) e digite o comando abaixo para ver a versão instalada:
docker --version
Agora, vamos rodar seu primeiro container de teste oficial:
docker run hello-world
O que acabou de acontecer?
1. O Docker procurou a imagem "hello-world" no seu computador.
2. Não achou, então foi até o Docker Hub (nuvem) e baixou.
3. Criou um container, executou a mensagem de boas-vindas e desligou.
Tudo isso em questão de segundos.
2. O Ciclo de Vida do Docker: Entendendo a Trindade
Muitos iniciantes travam no Docker porque confundem "Imagem" com "Container". Para nunca mais esquecer, vamos aprofundar nossa analogia culinária e ver os comandos que representam cada etapa.
☁️ 1. Registry (O Supermercado)
O Conceito: É o catálogo global. Assim como você vai ao mercado comprar ingredientes, o Docker vai ao Registry baixar softwares prontos. O principal é o Docker Hub.
Existem dois tipos de produtos nesse mercado:
- Imagens Oficiais: Criadas pelas próprias empresas (ex: Python, Node, MySQL). São seguras e otimizadas.
- Imagens da Comunidade: Criadas por usuários comuns. Cuidado com estas!
Comando Prático: docker pull (Baixar
da prateleira).
📜 2. Image (A Receita Imutável)
O Conceito: Depois que você baixa o software, ele vira uma Imagem no seu HD. A característica mais importante dela é ser Somente Leitura (Read-Only).
Você nunca "edita" uma imagem. Se quiser mudar algo (adicionar um tempero), você precisa criar uma nova imagem baseada na anterior. Isso garante que a receita original nunca seja estragada.
Comando Prático: docker images (Ver
seu livro de receitas).
📦 3. Container (O Bolo no Forno)
O Conceito: É a execução. O Docker pega a cópia da imagem e adiciona uma camada fina de "escrita" por cima.
A Mágica do Isolamento: Se você queimar o bolo (travar o container), a receita (imagem) continua intacta. Você pode simplesmente jogar o container fora e criar outro novo em folha em milissegundos.
Comando Prático: docker run (Assar o
bolo).
Tutorial Passo a Passo: O Ciclo Completo
Vamos ver essa trindade funcionando na prática. Faremos o download de um mini-servidor Python e o colocaremos para rodar.
Passo 1: Ir ao Mercado (Registry)
Vamos baixar uma imagem super leve do Python chamada "Alpine". Digite no terminal:
# O comando 'pull' vai até o Docker Hub e traz a imagem
docker pull python:alpine
Passo 2: Conferir a Receita (Image)
Verifique se ela foi baixada corretamente e está salva no seu disco:
docker images
# Saída esperada:
# REPOSITORY TAG IMAGE ID SIZE
# python alpine a1b2c3d4... 50MB
Note como ela é pequena (apenas ~50MB) comparada a instalar o Python no Windows.
Passo 3: Assar o Bolo (Container)
Agora vamos criar um container que imprime a versão do Python e depois se autodestrói (para não ocupar espaço).
# Traduzindo o comando:
# docker run : Crie e inicie um container
# --rm : Apague o container assim que ele terminar (limpeza automática)
# python:alpine : Use esta imagem
# python --version : O comando que quero rodar lá dentro
docker run --rm python:alpine python --version
Dica Pro: Você pode ter 50 containers rodando
baseados nessa mesma imagem python:alpine. Eles não
ocupam 50x o espaço em disco, pois todos compartilham a mesma
imagem base (Read-Only). O Docker é inteligente!
3. Tutorial Prático: Seu Primeiro Servidor Web (Nginx)
Chega de teoria. Vamos colocar a mão na massa e subir um servidor web profissional em menos de 1 minuto. O objetivo é ver uma página HTML no seu navegador servida por um container, sem instalar o Nginx no seu Windows/Mac/Linux.
Passo 1: O "Check-up" Inicial
Antes de tentar correr, vamos ver se conseguimos andar. Abra seu terminal e garanta que o Docker Desktop está aberto e rodando.
docker ps
Se aparecer uma tabela vazia (CONTAINER ID, IMAGE...), ótimo! Se der erro, abra o aplicativo do Docker Desktop primeiro.
Passo 2: O Comando de Lançamento
Copie e cole o comando abaixo. Não se assuste se aparecer "Unable to find image...", isso significa apenas que o Docker está baixando a imagem pela primeira vez.
docker run -d -p 8080:80 --name meu-site nginx
Passo 3: Dissecando o Comando (Entenda para não Decorar)
Cada parte desse comando tem um propósito vital. Vamos entender a lógica:
-
docker run: A ordem principal. "Crie e inicie um novo container". -
nginx: A imagem base. É o software que queremos rodar. -
-d(Detach Mode): Roda em "segundo plano". Sem isso, seu terminal ficaria travado rodando o servidor. Com isso, ele libera o terminal para você continuar usando. -
--name meu-site: Batiza o container. Sem isso, o Docker inventa nomes aleatórios (como vigilant_einstein), o que dificulta achar depois.
A Mágica das Portas (-p 8080:80)
Essa é a parte onde 90% dos iniciantes se confundem.
- 8080 (Lado Esquerdo): É a porta no SEU computador (Host). Você pode mudar para 3000, 4000, 9090...
- 80 (Lado Direito): É a porta DENTRO do container. O Nginx padrão escuta na porta 80. Você não pode mudar isso a menos que altere a configuração do Nginx.
- A Ponte: O comando cria um túnel. Tudo que chega na sua porta 8080 é teletransportado para a porta 80 do container.
Passo 4: O Teste Real
Agora, abra seu navegador (Chrome, Edge, etc.) e acesse:
Se você viu a mensagem "Welcome to nginx!", parabéns! Você tem um container rodando.
Passo 5: Limpando a Casa (Ciclo de Vida)
Diferente de programas normais que você fecha no "X", o container
continua rodando em segundo plano (lembra do -d?).
Vamos aprender a desligá-lo corretamente.
1. Verifique se ele está lá:
docker ps
Você verá o container "meu-site" na lista.
2. Pare o container (Desligar):
docker stop meu-site
Se você atualizar o navegador agora, o site terá saído do ar.
3. Remova o container (Jogar fora):
docker rm meu-site
Isso libera o nome "meu-site" para ser usado novamente e limpa seu disco.
4. Dockerfile: A Receita da Automação
Até agora usamos imagens criadas por outras pessoas (Nginx, Python). Mas o verdadeiro poder do Docker surge quando você empacota a SUA aplicação.
Para isso, usamos um arquivo de texto simples chamado
Dockerfile (exatamente assim, sem extensão .txt). Ele
é um manual de instruções que diz ao Docker: "Pegue este Linux,
instale este programa, copie meus arquivos e inicie o servidor".
4.1. Passo a Passo: Criando sua Primeira Imagem
Vamos simular um cenário real. Imagine que você tem uma API simples em Node.js.
Passo 1: Preparar os Arquivos
Crie uma pasta vazia e coloque dois arquivos nela:
-
package.json(Gerenciador de dependências do Node). server.js(O código do seu site/app).
Passo 2: Escrever o Dockerfile
Crie um arquivo chamado Dockerfile e cole o conteúdo
abaixo. Vamos dissecar cada linha para você entender a engenharia
por trás.
# 1. A BASE (O Alicerce)
# "Comece com uma imagem Linux leve que já tenha o Node v18 instalado"
FROM node:18-alpine
# 2. O ENDEREÇO (Organização)
# "Crie uma pasta /app dentro do container e entre nela"
WORKDIR /app
# 3. A ESTRATÉGIA DE CACHE (Dica de Ouro)
# "Copie apenas o arquivo de dependências primeiro"
COPY package.json .
# 4. A INSTALAÇÃO
# "Baixe as bibliotecas necessárias"
RUN npm install
# 5. O CÓDIGO
# "Agora sim, copie todo o resto dos arquivos do meu PC para o Container"
COPY . .
# 6. A DOCUMENTAÇÃO
# "Avise que esse container usa a porta 3000"
EXPOSE 3000
# 7. A IGNIÇÃO
# "Quando o container iniciar, rode este comando:"
CMD ["npm", "start"]
4.2. Entendendo a "Mágica" do Layer Caching
Você notou que copiamos o package.json (Passo 3)
separado do resto dos arquivos (Passo 5)? Isso não é por acaso. É
Engenharia de Performance.
O Docker constrói a imagem em camadas (Layers), como um bolo.
-
Como funciona: Se você mudar uma linha de
código no
server.js, o Docker percebe que opackage.jsonNÃO mudou. -
O Resultado: Ele reutiliza a camada do
npm installdo cache (que é a parte demorada) e apenas refaz a cópia do código final. - Benefício: Seu "Build" cai de 2 minutos para 0.5 segundos.
4.3. Passo 3: O Build (Construindo a Imagem)
Agora que a receita está escrita, precisamos "cozinhar". No terminal, dentro da pasta do projeto, rode:
docker build -t minha-api-node .
Entendendo o comando:
docker build: A ordem de construção.-
-t minha-api-node: A "Tag" (Nome). Estamos batizando a imagem. -
.(Ponto Final): MUITO IMPORTANTE! Diz ao Docker: "Procure o Dockerfile na pasta onde estou agora".
4.4. Passo 4: Rodando sua Criação
Agora que a imagem minha-api-node existe no seu
computador (verifique com docker images), vamos criar
um container com ela.
docker run -d -p 3000:3000 --name meu-app-node minha-api-node
Pronto! Se você acessar http://localhost:3000, verá
sua aplicação rodando. Você acabou de empacotar e executar seu
próprio software em um ambiente isolado.
Resumo da Ópera:
1. Dockerfile: Escreve a receita.
2. Build: Transforma receita em Imagem.
3. Run: Transforma Imagem em Container.
5. Docker Compose: O Maestro da Orquestra
Imagine que sua aplicação é uma banda. O Node.js é o guitarrista, o Postgres é o baterista e o Redis é o baixista.
Rodar docker run para cada um deles é como pedir para
cada músico tocar em uma sala diferente, sem se ouvirem. É o caos.
O Docker Compose é o Maestro. Ele garante que
todos subam no palco juntos, na hora certa, e saibam conversar
entre si.
Ele funciona através de um arquivo de texto chamado
docker-compose.yml. Vamos construir um agora mesmo.
Passo a Passo: Sua Primeira Orquestração
Vamos criar um ambiente completo: uma API conectada a um Banco de Dados.
Passo 1: Criar o Arquivo
Na raiz do seu projeto (onde está o Dockerfile), crie um arquivo
chamado docker-compose.yml.
Passo 2: Definir a Arquitetura (O Código)
Copie o código abaixo. Atenção: O arquivo YAML é "alérgico" a tabulações. Use apenas espaços para indentar.
version: '3.8' # Versão da sintaxe do Compose
services:
# --- SERVIÇO 1: APLICAÇÃO (BACKEND) ---
api-node:
build: . # "Construa a imagem usando o Dockerfile desta pasta"
ports:
- "3000:3000" # "Abra a porta 3000 para o meu PC"
depends_on:
- banco_postgres # "Só inicie depois que o banco estiver de pé"
environment:
- DB_HOST=banco_postgres # O endereço do banco é o NOME do serviço abaixo!
# --- SERVIÇO 2: BANCO DE DADOS ---
banco_postgres:
image: postgres:15 # "Baixe a imagem pronta do Docker Hub"
environment:
POSTGRES_PASSWORD: senha_secreta # Configuração obrigatória do Postgres
volumes:
- dados-do-banco:/var/lib/postgresql/data # "Salve os dados aqui!"
# --- PERSISTÊNCIA (VOLUMES) ---
volumes:
dados-do-banco: # Cria uma "pasta virtual" segura no Docker
Entendendo os Conceitos Críticos
1. Networking Mágico (DNS Automático)
Como o Node acha o Banco de Dados? Você não usa
localhost. No mundo do Docker Compose,
o nome do serviço vira o endereço.
Se você chamou o serviço de banco_postgres, sua API
vai conectar em: postgres://banco_postgres:5432. O
Docker resolve isso sozinho.
2. Volumes (A Salvação dos Dados)
Por padrão, containers são efêmeros. Se você deletar o container do banco, seus dados somem.
Para evitar isso, usamos volumes. A linha
dados-do-banco:/var... diz ao Docker: "Crie um cofre
separado do container. Mesmo se o container explodir, mantenha os
arquivos do banco guardados nesse cofre".
Passo 3: A Execução
Agora vem a mágica. Esqueça aqueles comandos longos. Abra o terminal e digite:
docker-compose up -d
- up: Sobe toda a infraestrutura (cria redes, volumes e containers).
- -d: Detach (libera o terminal).
Para monitorar o que está acontecendo (Logs de tudo junto):
docker-compose logs -f
Para desligar tudo e remover os containers (Limpeza):
docker-compose down
Dica de Carreira: Em empresas reais, você raramente usará o comandodocker runmanual. Tudo é definido em arquivosdocker-compose.ymlpara garantir que todos os desenvolvedores da equipe rodem o projeto exatamente da mesma maneira.
6. O Cinto de Utilidades: Comandos Essenciais
Você não precisa decorar a documentação inteira. No dia a dia de um engenheiro DevOps ou Desenvolvedor, usamos apenas cerca de 10 comandos recorrentes.
Para facilitar, dividimos os comandos em três categorias: Ciclo de Vida (Ligar/Desligar), Limpeza (Faxina) e Investigação (Sherlock Holmes).
6.1. Ciclo de Vida (Gerenciamento)
Comandos para controlar o estado dos seus containers.
| Comando | O que faz? | Exemplo Real |
|---|---|---|
docker ps |
Mostra o que está rodando agora. | docker ps |
docker ps -a |
Mostra TUDO (inclusive os que deram erro ou pararam). | docker ps -a |
docker start [id] |
Liga um container que estava desligado. | docker start meu-site |
docker stop [id] |
Desliga o container com segurança (envia sinal SIGTERM). | docker stop meu-site |
6.2. A Grande Faxina (Limpeza)
Docker consome muito disco se você não limpar. Use com cuidado.
| Comando | O que faz? | Diferença Chave |
|---|---|---|
docker rm [id] |
Apaga um CONTAINER. | Só funciona se o container estiver parado (stop). |
docker rmi [id] |
Apaga uma IMAGEM (A receita). |
Libera espaço real no HD. Use
docker images para ver os IDs.
|
☢️ O Botão Nuclear (Use com sabedoria):
Se o seu disco estiver cheio e você quiser apagar TUDO que não está sendo usado (containers parados, redes vazias e imagens órfãs), rode:
docker system prune -a
6.3. Investigação (Debug)
Algo deu errado? O container não subiu? É hora de investigar.
A) docker logs (O Diário de Bordo)
Se seu container "morreu" assim que ligou, o motivo está aqui. Ele mostra tudo que a aplicação imprimiu no console (stdout).
# O flag -f (follow) deixa o log aberto rodando em tempo real (igual matrix)
docker logs -f meu-app-node
B) docker exec (O Teletransporte)
Este é o comando favorito dos profissionais. Ele permite que você entre dentro de um container que está rodando e execute comandos lá dentro, como se estivesse no terminal dele.
Cenário: Você quer verificar se um arquivo foi criado lá dentro ou testar a conexão com o banco.
# Sintaxe: docker exec -it [nome_container] [programa]
# -it = Modo Interativo (permite digitar)
# sh ou bash = O terminal que queremos abrir
docker exec -it meu-app-node sh
Ao rodar isso, seu prompt vai mudar (geralmente para um
#). Agora você está "na Matrix". Pode dar
ls, cd, cat dentro do Linux
do container. Para sair, digite exit.
Resumo Visual: RM vs RMI
A confusão mais comum de iniciantes é tentar apagar a imagem enquanto o container ainda existe.
- Você não pode jogar fora a Receita (Image) enquanto o Bolo (Container) está no forno.
- Ordem correta: Stop Container -> RM Container -> RMI Image.
7. Conclusão: Você desbloqueou um Superpoder
Chegamos ao fim. Se você seguiu este guia e rodou os comandos no seu terminal, você já não é mais o mesmo desenvolvedor de 30 minutos atrás.
Você deixou de ser refém do "na minha máquina funciona" e passou a dominar a Linguagem Universal da Infraestrutura. Hoje, saber Docker é o divisor de águas entre um programador amador e um Engenheiro de Software Sênior.
O Mapa do Tesouro (O que vem depois?)
O Docker é a peça fundamental, mas ele é apenas um tijolo. Para construir arranha-céus, você precisará aprender a gerenciar milhares desses containers.
- Agora: Pratique Docker Compose até sentir confiança.
- Em breve: Estude CI/CD (GitHub Actions) para criar containers automaticamente quando você salvar o código.
- O Chefão Final: Kubernetes (K8s). É ele quem gerencia os containers do Google, Amazon e Netflix. Mas não tenha pressa, domine a base primeiro.
🏆 Desafio Final (Integração):
Lembra do projeto "To-Do List" que criamos no
guia de JavaScript? Seu desafio é criar um
Dockerfile para ele.
1. Use uma imagem base do nginx:alpine.
2. Copie os arquivos HTML/CSS/JS para a pasta
/usr/share/nginx/html dentro do container.
3. Suba o site na porta 8080.
Se conseguir fazer isso, você oficialmente sabe colocar um site no
ar com Docker.
Boa sorte, a gente se vê no próximo nível! 🐳
