Voltar

Docker

Referência Rápida

Comando O que faz
docker run -d -p 8080:80 --name c nginx Criar e iniciar container
docker ps / docker ps -a Listar containers rodando / todos
docker stop / start / restart c Parar / iniciar / reiniciar container
docker rm -f c Forçar remoção de container
docker logs -f c Seguir logs em tempo real
docker exec -it c bash Abrir terminal no container
docker images Listar imagens locais
docker pull nginx:alpine Baixar imagem do Docker Hub
docker build -t app:1.0 . Construir imagem do Dockerfile
docker rmi nginx Remover imagem
docker volume ls / rm / prune Listar / remover / limpar volumes
docker network ls / create / rm Gerenciar redes
docker compose up -d Subir todos os serviços
docker compose down Derrubar todos os serviços
docker compose logs -f app Logs de um serviço
docker compose exec db psql ... Executar comando em serviço
docker system df Espaço usado pelo Docker
docker system prune -a Limpeza geral

Resumo

Docker

Empacotador de aplicação

Imagem

'Molde' de um container, define a estrutura uma vez e usa quantas vezes quiser facilmente (sem ter que construir) - armazena na sua máquina ou no hub.docker.com

Container

Instância rodando uma imagem, o processo/execução no sistema (pode ter vários processos originários de uma mesma imagem) - não armazena os dados (quando desliga a máquina tudo se perde)

Dockerfile

Arquivo que contém as instruções da construção da imagem, substitui a escrita/poluição no cmd

Volume

Onde persiste os dados em Docker, armazena os dados fora do container

Tipos Volume
Tipo Quando usar
Named Volume (recomendado) Gerenciado pelo Docker. Fica em /var/lib/docker/volumes/. Melhor para bancos de dados.
Bind Mount Conecta pasta específica do host ao container. Ideal para desenvolvimento (ver mudanças ao vivo).
tmpfs Mount Armazenamento em memória RAM. Temporário, muito rápido. Para dados sensíveis em memória.
Named Volumes na Prática
# Criar um volume manualmente
docker volume create dados-postgres

# Listar volumes
docker volume ls

# Inspecionar um volume (ver localização física, etc)
docker volume inspect dados-postgres

# Usar o volume no container
docker run -d \
  --name postgres \
  -v dados-postgres:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=senha \
  postgres:15

# Se remover e recriar o container, os dados persistem!
docker rm -f postgres
docker run -d \
  --name postgres \
  -v dados-postgres:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=senha \
  postgres:15
# Os dados ainda estão lá!

# Remover um volume (CUIDADO: apaga os dados!)
docker volume rm dados-postgres

# Remover volumes não utilizados
docker volume prune

Docker Compose

Ferramenta para gerir os containers, substitui o comando 'Docker run', escreve tudo em um arquivo YAML e sobe

Estrutura do docker-compose.yml

Um arquivo Compose tem quatro seções principais: version, services, volumes e networks.

version: '3.8'

# ─── SERVIÇOS ─────────────────────────────────────────────────
services:

  # Cada serviço é um container
  nome-do-servico:
    image: imagem:tag          # OU
    build:                     # Construir de um Dockerfile
      context: .               # Pasta com o Dockerfile
      dockerfile: Dockerfile   # Nome do arquivo (se não for 'Dockerfile')

    container_name: meu-app   # Nome fixo do container

    ports:
      - "HOST:CONTAINER"      # Mapeamento de portas

    environment:               # Variáveis de ambiente
      - VARIAVEL=valor
      DATABASE_URL: postgres://user:senha@db/meudb

    env_file:                  # Ou carrega de um arquivo .env
      - .env

    volumes:                   # Volumes e bind mounts
      - dados-nomeados:/var/dados
      - ./pasta-local:/app

    depends_on:               # Ordem de inicialização
      db:                     # Aguarda 'db' ficar 'healthy'
        condition: service_healthy

    restart: unless-stopped   # Política de reinício

    networks:                 # Redes que participa
      - minha-rede

    healthcheck:              # Verificação de saúde
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s


# ─── VOLUMES NOMEADOS ─────────────────────────────────────────
volumes:
  dados-nomeados:            # Volume gerenciado pelo Docker
  outro-volume:
    external: true           # Volume criado externamente


# ─── REDES ────────────────────────────────────────────────────
networks:
  minha-rede:
    driver: bridge
Comandos Docker Compose
# ─── SUBIR ────────────────────────────────────────────────────

# Subir todos os serviços em background
docker compose up -d

# Subir e reconstruir imagens (quando mudou Dockerfile/código)
docker compose up -d --build

# Subir apenas um serviço específico
docker compose up -d nome-do-servico


# ─── PARAR ────────────────────────────────────────────────────

# Para os containers (mantém volumes e networks)
docker compose stop

# Para e REMOVE containers e networks (volumes permanecem)
docker compose down

# Remove tudo incluindo volumes (CUIDADO: apaga dados!)
docker compose down -v


# ─── MONITORAR ────────────────────────────────────────────────

# Listar containers do projeto
docker compose ps

# Ver logs de todos os serviços
docker compose logs

# Seguir logs em tempo real
docker compose logs -f

# Logs de um serviço específico
docker compose logs -f app


# ─── EXECUTAR COMANDOS ────────────────────────────────────────

# Abrir terminal em um serviço
docker compose exec app bash

# Executar comando pontual
docker compose exec db psql -U usuario -d meudb

# Rodar um serviço one-off (sem iniciar outros)
docker compose run --rm app npm test


# ─── OUTROS ──────────────────────────────────────────────────

# Ver configuração final resolvida (variáveis substituídas)
docker compose config

# Rebuild de um serviço sem parar os outros
docker compose up -d --build app

# Escalar um serviço (criar múltiplas instâncias)
docker compose up -d --scale app=3

Docker Run

Baixa imagem, cria e inicia em um container

Flag O que faz
-d (--detach) Roda em background. Sem isso, o terminal fica preso no container.
-p HOST:CONTAINER Mapeia porta. Ex: -p 8080:80 — porta 8080 do seu PC entra na 80 do container.
--name NOME Dá um nome ao container. Facilita referenciar depois.
-e VAR=VALOR Define variável de ambiente dentro do container.
Ex: -e POSTGRES_USER=meususuario -e POSTGRES_PASSWORD=minhasenha123
-v ORIGEM:DESTINO Monta um volume — conecta pasta do host com pasta do container.
Ex: -v dados-postgres:/var/lib/postgresql/data
--rm Remove o container automaticamente quando ele parar.
-it Modo interativo com terminal. Use para entrar no container.
--network REDE Conecta o container a uma rede específica.
--restart always Reinicia o container automaticamente se ele parar ou o host reiniciar.

No fim do comando escreve a imagem que vai usar

Gerenciando Containers

Comandos do Dia a Dia
# ─── LISTAR ───────────────────────────────────────────────────

docker ps          # Containers em execução

docker ps -a       # Todos os containers (incluindo parados)

docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' # Formato personalizado/legível


# ─── INICIAR / PARAR ──────────────────────────────────────────

# Parar graciosamente (envia SIGTERM, aguarda 10s, depois SIGKILL)
docker stop meu-nginx

# Parar imediatamente (SIGKILL direto — use apenas se necessário)
docker kill meu-nginx

docker start meu-nginx      # Iniciar container parado

docker restart meu-nginx    # Reiniciar


# ─── REMOVER ──────────────────────────────────────────────────

docker rm meu-nginx         # Remover container parado

docker rm -f meu-nginx      # Forçar remoção de container rodando

docker container prune      # Remover todos os containers parados de uma vez


# ─── LOGS ────────────────────────────────────────────────────

docker logs meu-nginx                # Ver todos os logs

docker logs -f meu-nginx             # Seguir logs em tempo real (como tail -f)

docker logs --tail 50 meu-nginx      # Ver apenas as últimas 50 linhas

docker logs -t meu-nginx             # Logs com timestamp


# ─── ENTRAR NO CONTAINER ──────────────────────────────────────

docker exec -it meu-nginx bash             # Abrir terminal bash no container

docker exec -it meu-nginx sh               # Se a imagem não tiver bash, tente sh

docker exec meu-nginx ls /var/www/html     # Executar um comando pontual sem entrar


# ─── INSPECIONAR ──────────────────────────────────────────────

docker inspect meu-nginx          # Informações detalhadas do container (JSON)

docker stats                      # Ver uso de CPU, memória e rede em tempo real

docker stats meu-nginx            # Stats de um container específico

Gerenciando Imagens


docker images                    # Listar imagens baixadas localmente

# Baixar imagem sem criar container
docker pull postgres:15
docker pull node:20-alpine

docker rmi nginx                 # Remover uma imagem

docker image prune               # Remover imagens não utilizadas (dangling)

docker image prune -a            # Remover TODAS as imagens não utilizadas por nenhum container

docker search postgres           # Pesquisar imagem no Docker Hub via terminal

Dockerfile (criar sua própria img)

Instrução O que faz
FROM imagem:tag Define a imagem base. Sempre a primeira instrução.
WORKDIR /caminho Define o diretório de trabalho dentro do container.
COPY origem destino Copia arquivos do host para o container.
ADD origem destino Como COPY, mas suporta URLs e descompacta tar automaticamente.
RUN comando Executa comando durante o BUILD da imagem (instalar pacotes, etc).
CMD ["cmd", "arg"] Comando padrão ao iniciar o container. Pode ser sobrescrito.
ENTRYPOINT ["cmd"] Ponto de entrada fixo do container. CMD vira argumentos dele.
ENV VAR=VALOR Define variável de ambiente disponível em runtime.
ARG VAR=VALOR Variável disponível APENAS no momento do build.
EXPOSE porta Documenta qual porta o container vai usar (não abre automaticamente).
VOLUME /caminho Declara um ponto de montagem de volume.
USER usuario Define o usuário que roda os próximos comandos (segurança).
Exemplo de Dockerfile
# ─────────────────────────────────────────────────────────────
# ESTÁGIO 1: Instalação de dependências
# ─────────────────────────────────────────────────────────────
FROM node:20-alpine AS dependencies

# Instala dependências nativas se necessário
# (bcrypt, sharp e outros precisam de ferramentas de compilação)
RUN apk add --no-cache python3 make g++

WORKDIR /app

# Copia APENAS os arquivos de dependência primeiro
# Isso aproveita o cache do Docker:
# Se package.json não mudou, essa camada é reutilizada
COPY package.json package-lock.json ./

# Instala dependências de produção
RUN npm ci --only=production


# ─────────────────────────────────────────────────────────────
# ESTÁGIO 2: Imagem final (menor e mais segura)
# ─────────────────────────────────────────────────────────────
FROM node:20-alpine

# Cria usuário não-root para rodar a aplicação (segurança!)
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

# Copia node_modules do estágio anterior
COPY --from=dependencies /app/node_modules ./node_modules

# Copia o código da aplicação
COPY . .

# Altera dono dos arquivos para o usuário criado
RUN chown -R appuser:appgroup /app

# Troca para o usuário não-root
USER appuser

# Documenta a porta (boa prática, não obrigatório)
EXPOSE 3000

# Variáveis de ambiente com valores padrão
ENV NODE_ENV=production
ENV PORT=3000

# Verifica se a aplicação está saudável
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"

# Inicia a aplicação
CMD ["node", "src/server.js"]
Construindo e Publicando Imagens
docker build -t minha-app:1.0 .     # Construir a imagem com a tag 'minha-app:1.0'
                                    # O ponto (.) indica que o Dockerfile está na pasta atual

docker build -f caminho/Dockerfile -t minha-app .   # Para usar um Dockerfile em outro lugar

docker history minha-app:1.0        # Ver as camadas e tamanho da imagem construída

# ─── Publicar no Docker Hub ───────────────────────────────────
docker login    # Faça login no Docker Hub

docker tag minha-app:1.0 seuusuario/minha-app:1.0    # Taguear a imagem com seu usuário Docker Hub

docker push seuusuario/minha-app:1.0      # Enviar para o Docker Hub
Bind Mounts — Desenvolvimento Local

Bind mounts são indispensáveis no desenvolvimento. Eles espelham sua pasta local dentro do container — qualquer alteração no código é refletida imediatamente no container, sem precisar reconstruir a imagem.

# Montar a pasta atual dentro do container
docker run -d \
  --name app-dev \
  -p 3000:3000 \
  -v $(pwd):/app \
  -v /app/node_modules \
  node:20-alpine \
  sh -c 'npm install && npm run dev'

# O que aconteceu:
# -v $(pwd):/app          = pasta atual do host mapeada para /app no container
# -v /app/node_modules    = volume anônimo para node_modules (não sobrescreve!)

# No Windows PowerShell, use ${PWD} no lugar de $(pwd)
docker run -v ${PWD}:/app ...
Exemplo Real — Node.js + PostgreSQL + Redis

Estrutura do Projeto

meu-projeto/
├── src/
│   └── server.js
├── Dockerfile
├── docker-compose.yml
├── docker-compose.override.yml   # Sobrescreve configs para dev
├── .dockerignore
├── .env                          # Variáveis (não versionar!)
├── .env.example                  # Template (versionar)
└── package.json

Arquivo .env

# .env — NÃO commite esse arquivo no git!
# Adicione .env no .gitignore

# Aplicação
NODE_ENV=development
PORT=3000
APP_SECRET=sua-chave-secreta-aqui

# PostgreSQL
POSTGRES_USER=appuser
POSTGRES_PASSWORD=senhasegura123
POSTGRES_DB=meuapp
DATABASE_URL=postgresql://appuser:senhasegura123@db:5432/meuapp

# Redis
REDIS_URL=redis://redis:6379

Arquivo .dockerignore

# .dockerignore — equivalente ao .gitignore para Docker
# Evita copiar arquivos desnecessários para a imagem

node_modules
.git
.gitignore
.env
.env.*
*.log
docker-compose*.yml
README.md
.DS_Store
coverage/
.nyc_output/
dist/            # Ou build/ — será compilado dentro do container

docker-compose.yml — Produção

version: '3.8'

services:

  # ─── APLICAÇÃO ───────────────────────────────────────────────
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: production      # Estágio do multi-stage build
    ports:
      - "${PORT:-3000}:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
      - REDIS_URL=${REDIS_URL}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - app-net

  # ─── BANCO DE DADOS ──────────────────────────────────────────
  db:
    image: postgres:15-alpine
    env_file: .env
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - app-net

  # ─── CACHE ───────────────────────────────────────────────────
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes --maxmemory 256mb
    volumes:
      - redis-data:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app-net

  # ─── PROXY REVERSO ───────────────────────────────────────────
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - certbot-data:/etc/letsencrypt
    depends_on:
      - app
    restart: unless-stopped
    networks:
      - app-net

volumes:
  postgres-data:
  redis-data:
  certbot-data:

networks:
  app-net:
    driver: bridge

docker-compose.override.yml — Desenvolvimento

O Docker Compose mescla automaticamente o arquivo override com o principal. Use isso para manter configurações de dev separadas sem modificar o arquivo de produção.

# docker-compose.override.yml
# Este arquivo é mesclado AUTOMATICAMENTE com docker-compose.yml
# Use para configs de desenvolvimento

version: '3.8'

services:
  app:
    build:
      target: development     # Usa estágio dev do Dockerfile
    volumes:
      - .:/app                # Bind mount para hot reload
      - /app/node_modules     # Preserva node_modules do container
    environment:
      - NODE_ENV=development
    command: npm run dev      # Sobrescreve CMD do Dockerfile

  db:
    ports:
      - "5432:5432"          # Expõe porta para conectar externamente

  redis:
    ports:
      - "6379:6379"