O que voce vai aprender neste tutorial
- Escrita de Dockerfile e significado de cada instrucao
- Build de imagem e inicializacao de container
- Gerenciamento de multiplos containers com docker-compose
- Construcao de ambiente de desenvolvimento Node.js + PostgreSQL
Pre-requisitos: Docker Desktop instalado. Se
docker --versionexibir a versao, esta tudo certo.
O que e Docker? Por que foi criado?
Historia da tecnologia de containers
As raizes da tecnologia de containers remontam ao chroot do UNIX V7 em 1979. Depois disso, evoluiu da seguinte forma:
| Ano | Tecnologia | Descricao |
|---|---|---|
| 1979 | chroot | Isolamento de sistema de arquivos |
| 2000 | FreeBSD Jail | Isolamento de processos |
| 2006 | cgroups (Google) | Limitacao de recursos |
| 2008 | LXC (Linux Containers) | Containers leves para Linux |
| 2013 | Docker | Padronizacao e popularizacao de containers |
O nascimento do Docker
Em 2013, Solomon Hykes (dotCloud) apresentou o Docker.
“Docker tornou possivel empacotar aplicacoes facilmente e executa-las da mesma forma em qualquer lugar” — Docker oficial
Por que o Docker foi revolucionario
- Compartilhar o “ambiente que funciona”: Resolveu o problema “funciona no meu ambiente”
- Leve: Diferente de VMs, compartilha o OS, iniciando em segundos
- Reprodutibilidade de imagem: Reproducao completa do ambiente via Dockerfile
- Ecossistema: Compartilhamento de imagens via Docker Hub
Diferenca entre VM e Container
flowchart TB
subgraph VM["Maquina Virtual (VM)"]
direction TB
AppA1["App A"] & AppB1["App B"]
GuestOS1["Guest OS"] & GuestOS2["Guest OS"]
Hypervisor["Hypervisor"]
HostOS1["Host OS"]
HW1["Hardware"]
end
subgraph Container["Container"]
direction TB
AppA2["App A"] & AppB2["App B"]
Runtime["Container Runtime<br/>(Docker)"]
HostOS2["Host OS"]
HW2["Hardware"]
end
| Caracteristica | VM | Container |
|---|---|---|
| Tempo de inicializacao | Minutos | Segundos |
| Uso de memoria | GB | MB |
| Nivel de isolamento | Completo | Nivel de processo |
| Independencia de OS | Completa | Kernel compartilhado |
Documentacao oficial: Docker overview
Conceitos basicos do Docker
Imagem e Container
- Imagem (Image): “Planta” da aplicacao. Somente leitura
- Container: “Instancia em execucao” criada a partir da imagem
flowchart LR
subgraph Static["Estatico"]
Dockerfile["Dockerfile"]
Image["node:20<br/>(Imagem)"]
end
subgraph Dynamic["Dinamico"]
Container["Em execucao<br/>(Container)"]
Stdout["stdout<br/>(Logs)"]
end
Dockerfile -->|build| Image
Image -->|run| Container
Container -->|logs| Stdout
Estrutura de camadas da imagem
Imagens Docker sao compostas por camadas, e apenas as partes alteradas sao reconstruidas:
FROM node:20-alpine # Camada base (~100MB)
WORKDIR /app # Camada de configuracao (~0KB)
COPY package*.json ./ # Camada de dependencias (~1KB)
RUN npm install # Camada node_modules (~50MB)
COPY . . # Camada de codigo da app (~10KB)
Melhor pratica: Coloque itens que mudam menos frequentemente no topo e os mais frequentes embaixo para usar o cache de forma eficiente
Step 1: Criacao da estrutura do projeto
Primeiro, crie a estrutura de diretorios do projeto.
mkdir docker-tutorial
cd docker-tutorial
mkdir src
touch Dockerfile docker-compose.yml src/index.js package.json
Step 2: Criacao da aplicacao Node.js
Crie um servidor Express simples.
package.json
{
"name": "docker-tutorial",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js"
},
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
src/index.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({
message: 'Hello from Docker!',
timestamp: new Date().toISOString()
});
});
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Step 3: Criacao do Dockerfile
O Dockerfile e a planta para construir a imagem.
Dockerfile
# Especificar imagem base
FROM node:20-alpine
# Definir diretorio de trabalho
WORKDIR /app
# Copiar arquivos de dependencias (otimizacao de cache)
COPY package*.json ./
# Instalar dependencias
RUN npm install
# Copiar codigo da aplicacao
COPY . .
# Expor porta (para documentacao)
EXPOSE 3000
# Comando de inicializacao
CMD ["npm", "start"]
Explicacao detalhada das instrucoes do Dockerfile
| Instrucao | Descricao | Exemplo |
|---|---|---|
FROM | Especifica imagem base | FROM node:20-alpine |
WORKDIR | Define diretorio de trabalho | WORKDIR /app |
COPY | Copia arquivos | COPY . . |
RUN | Executa comando no build | RUN npm install |
CMD | Comando padrao ao iniciar container | CMD ["npm", "start"] |
ENTRYPOINT | Ponto de entrada do container | ENTRYPOINT ["node"] |
ENV | Define variavel de ambiente | ENV NODE_ENV=production |
EXPOSE | Expoe porta (documentacao) | EXPOSE 3000 |
ARG | Argumento de build | ARG VERSION=1.0 |
Diferenca entre CMD e ENTRYPOINT
# CMD: Comando padrao que pode ser sobrescrito
CMD ["npm", "start"]
# docker run myapp npm run dev ← sera sobrescrito
# ENTRYPOINT: Comando sempre executado
ENTRYPOINT ["node"]
CMD ["index.js"]
# docker run myapp app.js ← executa como node app.js
Documentacao oficial: Dockerfile reference
Step 4: Build e execucao da imagem
# Build da imagem
docker build -t my-node-app .
# Verificar imagem construida
docker images
# Iniciar container
docker run -p 3000:3000 my-node-app
# Iniciar em background
docker run -d -p 3000:3000 --name my-app my-node-app
# Acesse http://localhost:3000 no navegador
Opcoes comuns do docker run
docker run \
-d # Modo detached (background)
-p 3000:3000 # Mapeamento de porta (host:container)
--name my-app # Nome do container
-e NODE_ENV=production # Variavel de ambiente
-v $(pwd):/app # Montagem de volume
--rm # Remocao automatica ao terminar
my-node-app # Nome da imagem
Step 5: Construcao de ambiente com docker-compose
Gerencie multiplos servicos (app + banco de dados) de uma vez.
docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgres://user:password@db:5432/mydb
volumes:
- ./src:/app/src # Para hot reload
depends_on:
- db
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
Estrutura do docker-compose.yml
version: '3.8' # Versao da especificacao Compose
services: # Definicao de servicos (containers)
service_name:
image: xxx # ou build: ./path
ports: # Mapeamento de portas
environment: # Variaveis de ambiente
volumes: # Volumes
depends_on: # Dependencias
restart: # Politica de reinicio
volumes: # Volumes nomeados
networks: # Redes personalizadas
Comandos docker-compose
# Iniciar todos os servicos
docker-compose up
# Iniciar em background
docker-compose up -d
# Rebuild e iniciar
docker-compose up --build
# Verificar logs
docker-compose logs -f app
# Iniciar apenas servico especifico
docker-compose up app
# Parar servicos
docker-compose down
# Remover incluindo volumes
docker-compose down -v
# Verificar status dos servicos
docker-compose ps
Hot reload: Ao montar o codigo fonte com
volumes, as alteracoes nos arquivos sao refletidas imediatamente no container.
Documentacao oficial: Docker Compose overview
Melhores praticas do Dockerfile
1. Build multi-estagio
Crie imagens leves para producao:
# Estagio de build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Estagio de producao
FROM node:20-alpine AS production
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
2. Uso do .dockerignore
Exclua arquivos desnecessarios do contexto de build:
.dockerignore
node_modules
npm-debug.log
.git
.gitignore
.env
*.md
.DS_Store
coverage
.nyc_output
3. Executar como usuario nao-root
Por seguranca, evite o usuario root:
FROM node:20-alpine
# Criar usuario nao-root
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
WORKDIR /app
COPY . .
# Mudar para usuario nao-root
USER nodejs
CMD ["node", "index.js"]
4. Adicionar health check
HEALTHCHECK \
CMD curl -f http://localhost:3000/health || exit 1
5. Principios do 12 Factor App
The Twelve-Factor App sao principios de design para aplicacoes cloud native:
- Configuracao: Gerenciar configuracao com variaveis de ambiente
- Dependencias: Declarar explicitamente (package.json)
- Porta: Expor servico via port binding
- Processos: Executar como processos stateless
- Logs: Emitir como streams para stdout
Comandos Docker mais usados
Operacoes de container
# Verificar containers em execucao
docker ps
# Verificar todos os containers (incluindo parados)
docker ps -a
# Executar comando dentro do container
docker exec -it container_name sh
# Verificar logs do container
docker logs container_name
docker logs -f container_name # Follow
# Parar container
docker stop container_name
# Remover container
docker rm container_name
# Remover todos os containers parados
docker container prune
Operacoes de imagem
# Listar imagens
docker images
# Remover imagem
docker rmi image_name
# Remover imagens nao utilizadas
docker image prune
# Verificar historico da imagem
docker history image_name
Limpeza
# Remover recursos nao utilizados de uma vez
docker system prune
# Remover incluindo volumes (cuidado!)
docker system prune -a --volumes
# Verificar uso de disco
docker system df
Solucao de problemas
Container nao inicia
# Verificar logs
docker logs container_name
# Iniciar em modo interativo para debug
docker run -it my-node-app sh
Porta em uso
# Verificar porta em uso
lsof -i :3000
# Mapear para outra porta
docker run -p 3001:3000 my-node-app
Build lento
- Verificar
.dockerignore - Otimizar ordem das camadas
- Usar build multi-estagio
Imagem muito grande
# Verificar tamanho da imagem
docker images
# Usar imagem base leve
FROM node:20-alpine # ~100MB (versao normal ~900MB)
# Remover arquivos desnecessarios
RUN npm ci --only=production && npm cache clean --force
Proximos passos
Apos dominar o basico do Docker, aprenda orquestracao:
- Introducao ao Kubernetes → Construir cluster Kubernetes
- Pipeline CI/CD → Construir CI/CD com GitHub Actions
Links de referencia
Documentacao oficial
- Documentacao oficial do Docker - Referencia oficial
- Dockerfile reference - Lista de instrucoes Dockerfile
- Docker Compose file reference - Especificacao Compose
- Docker Hub - Registro oficial de imagens
Melhores praticas
- Dockerfile best practices - Docker oficial
- The Twelve-Factor App - Principios de design para aplicacoes cloud native
- Docker Security Best Practices - OWASP
Ferramentas e recursos
- Docker Desktop - Ferramenta de gerenciamento GUI
- Dive - Ferramenta de analise de camadas de imagem Docker
- Hadolint - Ferramenta de analise estatica de Dockerfile
Cheat sheets
- Docker Cheat Sheet - Cheat sheet oficial do Docker
- Docker Compose Cheat Sheet - Lista de comandos mais usados