Docker para Iniciantes: Um Guia Prático de Introdução
· 12 min de leitura
📑 Índice
- O Que É Docker e Por Que Você Deveria Se Importar?
- Conceitos-Chave: Imagens, Contêineres e Dockerfiles
- Instalando Docker no Seu Sistema
- Comandos Essenciais do Docker Que Todo Desenvolvedor Precisa
- Escrevendo Seu Primeiro Dockerfile
- Docker Compose para Aplicações Multi-Contêiner
- Volumes: Persistindo Dados Além dos Ciclos de Vida dos Contêineres
- Fundamentos de Rede do Docker
- Melhores Práticas para Produção
- Depuração e Solução de Problemas Comuns
- Ferramentas e Integrações Populares
- Perguntas Frequentes
O Docker revolucionou o desenvolvimento de software ao resolver o infame problema "funciona na minha máquina". Em vez de instalar dependências diretamente no seu sistema e lidar com conflitos de versão, o Docker empacota tudo que sua aplicação precisa em contêineres isolados que executam de forma idêntica em qualquer lugar—do seu laptop aos servidores de produção.
Se você ainda não aprendeu Docker em 2026, agora é a hora. Ele se tornou o padrão de fato para implantação de aplicações, usado por mais de 13 milhões de desenvolvedores em todo o mundo e integrado em praticamente todos os fluxos de trabalho de desenvolvimento modernos.
O Que É Docker e Por Que Você Deveria Se Importar?
Docker é uma plataforma de conteinerização que envolve sua aplicação e todas as suas dependências em uma unidade padronizada chamada contêiner. Pense nele como um pacote leve e portátil que inclui tudo o que é necessário para executar seu software: código, runtime, ferramentas do sistema, bibliotecas e configurações.
Antes do Docker, desenvolvedores enfrentavam inconsistências constantes de ambiente. Sua aplicação Node.js poderia funcionar perfeitamente no seu MacBook com Node 18, mas travar na máquina Windows do seu colega executando Node 16. Ou pior, funcionaria em desenvolvimento mas falharia misteriosamente em produção por causa de diferenças sutis nas bibliotecas do sistema.
O Docker elimina essas dores de cabeça criando ambientes consistentes e reproduzíveis. Quando você conteineriza uma aplicação, está garantindo que ela se comportará da mesma forma independentemente de onde for executada.
Principais Benefícios de Usar Docker
- Consistência entre ambientes: Desenvolvimento, homologação e produção executam contêineres idênticos
- Integração mais rápida: Novos membros da equipe podem começar a contribuir em minutos em vez de passar dias configurando seu ambiente
- Isolamento: Execute múltiplos projetos com dependências conflitantes na mesma máquina sem interferência
- Uso eficiente de recursos: Contêineres compartilham o kernel do SO host, tornando-os muito mais leves que máquinas virtuais
- Implantação simplificada: Envie toda a sua pilha de aplicação como um único artefato
- Arquitetura de microsserviços: Divida aplicações monolíticas em serviços gerenciáveis e implantáveis independentemente
Dica profissional: Docker não é apenas para implantações em produção. Muitos desenvolvedores o usam para executar bancos de dados, camadas de cache e outros serviços localmente sem poluir seu sistema com instalações. Precisa de PostgreSQL para um projeto e MySQL para outro? Execute ambos em contêineres sem conflitos.
Conceitos-Chave: Imagens, Contêineres e Dockerfiles
Entender três conceitos fundamentais é essencial antes de mergulhar nos comandos e fluxos de trabalho do Docker.
Imagens Docker
Uma imagem é um modelo somente leitura que contém tudo o que é necessário para executar uma aplicação. Pense nela como uma classe em programação orientada a objetos—é um blueprint, não uma instância em execução.
Imagens são construídas em camadas, com cada camada representando uma mudança ou instrução. Essa arquitetura em camadas permite armazenamento e transferência eficientes porque o Docker só precisa baixar ou armazenar camadas que mudaram.
Você pode baixar imagens pré-construídas do Docker Hub (o registro oficial) ou construir suas próprias imagens personalizadas. Imagens base populares incluem node, python, nginx, postgres e redis.
Contêineres Docker
Um contêiner é uma instância em execução de uma imagem—como um objeto instanciado de uma classe. Uma imagem pode gerar múltiplos contêineres, cada um executando independentemente com seu próprio sistema de arquivos, rede e espaço de processo isolados.
Contêineres são efêmeros por design. Quando você para e remove um contêiner, quaisquer dados escritos dentro dele desaparecem a menos que você tenha configurado explicitamente armazenamento persistente usando volumes (mais sobre isso depois).
Dockerfiles
Um Dockerfile é um arquivo de texto contendo instruções para construir uma imagem Docker. É essencialmente uma receita que diz ao Docker como montar seu ambiente de aplicação passo a passo.
Cada instrução em um Dockerfile cria uma nova camada na imagem. O Docker armazena essas camadas em cache de forma inteligente, então reconstruir uma imagem só processa as camadas que mudaram—tornando construções subsequentes extremamente rápidas.
Aqui está um Dockerfile mínimo para uma aplicação Node.js:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Vamos detalhar o que cada instrução faz:
FROMespecifica a imagem base (Node.js 20 no Alpine Linux, uma distribuição mínima)WORKDIRdefine o diretório de trabalho dentro do contêinerCOPYtransfere arquivos da sua máquina host para o contêinerRUNexecuta comandos durante o processo de construção (instalando dependências)EXPOSEdocumenta em qual porta a aplicação escutaCMDdefine o comando padrão a ser executado ao iniciar um contêiner
Instalando Docker no Seu Sistema
A instalação do Docker varia ligeiramente por sistema operacional, mas o processo é direto em todas as principais plataformas.
macOS e Windows
Baixe e instale o Docker Desktop do site oficial. O Docker Desktop inclui tudo que você precisa: o Docker Engine, Docker CLI, Docker Compose e uma GUI amigável para gerenciar contêineres.
Após a instalação, o Docker Desktop executa em segundo plano e adiciona um ícone na barra de menu (macOS) ou ícone na bandeja do sistema (Windows) para acesso rápido às configurações e contêineres em execução.
Linux
No Linux, instale o Docker Engine diretamente usando o gerenciador de pacotes da sua distribuição. Para Ubuntu/Debian:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
Faça logout e login novamente para que a associação ao grupo tenha efeito, permitindo que você execute comandos Docker sem sudo.
Verificando a Instalação
Confirme que o Docker está funcionando corretamente executando:
docker --version
docker run hello-world
O segundo comando baixa uma pequena imagem de teste e a executa em um contêiner. Se você ver uma mensagem de boas-vindas, o Docker está instalado e funcionando corretamente.
Comandos Essenciais do Docker Que Todo Desenvolvedor Precisa
Dominar um punhado de comandos principais cobrirá 90% do seu uso diário do Docker. Aqui está uma tabela de referência abrangente:
| Comando | O Que Faz | Opções Comuns |
|---|---|---|
docker build -t myapp . |
Constrói uma imagem a partir de um Dockerfile no diretório atual | -t marca a imagem com um nome |
docker run myapp |
Cria e inicia um contêiner a partir de uma imagem | -d (desanexado), -p (mapeamento de porta), --name |
docker ps |
Lista contêineres em execução | -a mostra todos os contêineres (incluindo parados) |
docker stop [id] |
Para graciosamente um contêiner em execução | Use ID ou nome do contêiner |
docker rm [id] |
Remove um contêiner parado | -f força remoção de contêineres em execução |
docker images |
Lista todas as imagens no seu sistema | -a mostra imagens intermediárias |
docker rmi [image] |
Remove uma imagem | -f força remoção |
docker logs [id] |
Visualiza saída e logs do contêiner | -f segue a saída de log em tempo real |
docker exec -it [id] sh |
Abre um shell interativo dentro de um contêiner em execução | -it habilita terminal interativo |
docker pull [image] |
Baixa uma imagem de um registro | Especifique tag como nginx:1.25 |
docker compose up |
Inicia todos os serviços definidos no docker-compose.yml | -d executa em segundo plano |
docker compose down |
Para e remove todos os contêineres do arquivo compose | -v também remove volumes |
Exemplos Práticos de Comandos
Executando um contêiner com mapeamento de porta e variáveis de ambiente:
docker run -d \
--name my-postgres \
-p 5432:5432 \
-e POSTGRES_PASSWORD=secret \
postgres:16
Isso inicia o PostgreSQL em segundo plano, mapeia a porta 5432 para sua máquina host e define a senha do banco de dados.
Visualizando logs em tempo real de um contêiner:
docker logs -f my-postgres
Executando comandos dentro de um contêiner em execução:
docker exec -it my-postgres psql -U postgres
Isso abre um shell PostgreSQL interativo dentro do contêiner.
Dica rápida: Você não precisa digitar IDs completos de contêiner. O Docker aceita prefixos únicos, então se o ID do seu contêiner é a3f8b2c1d4e5, você pode usar docker stop a3f desde que nenhum outro ID de contêiner comece com esses caracteres.
Escrevendo Seu Primeiro Dockerfile
Vamos construir um Dockerfile completo para uma aplicação Node.js do mundo real, explicando cada decisão ao longo do caminho.
# Use uma versão específica do Node.js no Alpine Linux (tamanho de imagem menor)
FROM node:20-alpine
# Instale dependências do sistema se necessário
RUN apk add --no-cache python3 make g++
# Defina o diretório de trabalho
WORKDIR /app
# Copie os arquivos de pacote primeiro (para melhor cache de camadas)
COPY package*.json ./
# Instale apenas dependências de produção
RUN npm ci --production --silent
# Copie o código-fonte da aplicação
COPY . .
# Crie um usuário não-root para segurança
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 && \
chown -R nodejs:nodejs /app
# Mude para usuário não-root
USER nodejs
# Exponha a porta da aplicação
EXPOSE 3000
# Verificação de saúde para monitorar status do contêiner
HEALTHCHECK --interval=30s --timeout=3s \
CMD node healthcheck.js || exit 1
# Inicie a aplicação
CMD ["node", "server.js"]
Melhores Práticas de Dockerfile
A ordem importa para eficiência de cache. Coloque instruções que mudam frequentemente (como COPY . .) perto do final do seu Dockerfile. Dessa forma, o Docker pode reutilizar camadas em cache para instalação de dependências quando apenas seu código-fonte muda.
Use arquivos .dockerignore para excluir arquivos desnecessários do contexto de construção:
node_modules
npm-debug.log
.git
.env
*.md
.DS_Store
Isso acelera construções e reduz o tamanho da imagem impedindo que o Docker copie arquivos que você não precisa no contêiner.
Construções Multi-Estágio
Para linguagens compiladas ou aplicações que requerem ferramentas de construção, use construções multi-estágio para manter as imagens finais pequenas:
# Estágio de construção
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Estágio de produção
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]
A imagem final contém apenas dependências de produção e artefatos compilados, não ferramentas de construção ou código-fonte.
Docker Compose para Aplicações Multi-Contêiner
Aplicações do mundo real raramente consistem em um único serviço. Você normalmente precisa de uma aplicação web, banco de dados, cache, fila de mensagens e outros serviços de suporte. O Docker Compose permite definir e gerenciar aplicações multi-contêiner usando um único arquivo de configuração YAML.
Aqui está um docker-compose.yml completo para uma pilha típica de aplicação web:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
volumes:
- ./logs:/app/logs
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=secret
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redisdata:/data
restart: unless-stopped
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
restart: unless-stopped
volumes:
pgdata:
redisdata:
Trabalhando com Docker Compose
Inicie todos os serviços em segundo plano:
dock