Skip to content
Foreman ou Docker Compose? O ambiente local ideal para Rails em 2026

Foreman ou Docker Compose? O ambiente local ideal para Rails em 2026

TL;DR

Rode web, css, js e workers nativos com bin/dev e Foreman. Coloque só Postgres e Redis em um compose mínimo, com a mesma versão de produção. No Mac, troque Docker Desktop por OrbStack para cortar RAM e disco. Reserve o compose completo ou devcontainer para onboarding de time e dependências nativas difíceis.

Tudo nativo com Procfile.dev ou tudo em container com docker-compose? A resposta que funciona melhor no dia a dia é um meio-termo: app nativa, serviços com estado em container, e um runtime de containers que não devora sua RAM.

Publicado em 6 min de leitura

Também disponível em English

Compartilhar

Todo projeto Rails chega nessa encruzilhada. De um lado, o Procfile.dev com Foreman subindo web, css, js e Sidekiq, com Postgres e Redis instalados direto na máquina. Do outro, um docker-compose.yml com tudo configurado, que funciona igual em qualquer máquina, mas transforma o notebook em um aquecedor e come gigabytes de disco.

Depois de muitos anos alternando entre os dois, minha recomendação é clara: nenhum dos extremos. Use um setup híbrido.

O setup híbrido em uma frase

Os processos da aplicação (Rails, watchers de CSS e JS, workers) rodam nativos via bin/dev. Os serviços com estado (Postgres e Redis) rodam em container, em um compose mínimo. No Mac, o runtime de containers é o OrbStack, não o Docker Desktop.

Por que não rodar Rails dentro do container no Mac

O maior custo do Docker no macOS não é o container em si, é o bind mount. Seu código mora no sistema de arquivos do Mac e o container roda dentro de uma VM Linux. Cada leitura de arquivo atravessa essa fronteira. Para Rails, isso pesa em tudo:

  • boot da aplicação e eager loading do Zeitwerk;
  • reload de código a cada request em desenvolvimento;
  • watchers do Tailwind, esbuild ou Vite observando milhares de arquivos;
  • suíte de testes lendo fixtures e factories.

Com Ruby nativo, esse custo some. De quebra, debug, binding.irb e integração com o editor funcionam sem configuração extra de portas ou TTY.

Por que ainda usar container para os serviços

Instalar Postgres e Redis via Homebrew é o caminho mais leve, mas tem um problema clássico: drift de versão. Você tem um projeto em Postgres 16, outro em 18, e a produção no RDS em uma terceira versão. Com container você ganha:

  • paridade com produção: a tag da imagem é a mesma major do seu banco gerenciado;
  • isolamento por projeto: cada app tem seu volume, sem disputa de porta ou de extensão;
  • reset trivial: docker compose down -v e você recomeça do zero.

E o custo é baixo. Postgres e Redis ociosos ocupam pouca memória. O que pesava no seu setup antigo era o resto da stack dentro de containers e, principalmente, o próprio Docker Desktop.

O compose mínimo

# compose.yml
services:
  db:
    image: postgres:18
    environment:
      POSTGRES_PASSWORD: postgres
    ports: ["5432:5432"]
    volumes:
      - pgdata:/var/lib/postgresql
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 5s
      retries: 10

  redis:
    image: redis:8-alpine
    ports: ["6379:6379"]

volumes:
  pgdata:

Atenção ao volume: a partir da imagem oficial do Postgres 18, o diretório de dados passou a ficar dentro de um subdiretório por versão. Por isso o volume é montado em /var/lib/postgresql, e não mais em /var/lib/postgresql/data como nos exemplos antigos. Isso também facilita upgrades futuros com pg_upgrade.

Sobre o Redis: o Redis 8 voltou a ter uma opção de licença open source (AGPL). Se a licença for um problema na sua empresa, o Valkey é um substituto compatível, com licença BSD. Basta trocar a imagem.

O Procfile.dev

# Procfile.dev
web: bin/rails server -p 3000
css: bin/rails tailwindcss:watch
js: yarn build --watch
worker: bundle exec sidekiq

E as variáveis de ambiente apontando para os containers:

# .env
DATABASE_URL=postgres://postgres:postgres@localhost:5432
REDIS_URL=redis://localhost:6379/0

Para ter um comando só, faça o bin/dev subir os serviços antes do Foreman:

#!/usr/bin/env sh
docker compose up -d --wait
exec foreman start -f Procfile.dev "$@"

O --wait respeita o healthcheck, então o Rails só sobe quando o Postgres já aceita conexões.

Versões de Ruby e Node ficam em um .tool-versions gerenciado pelo mise, versionado junto com o projeto. Assim o "nativo" também é reproduzível.

OrbStack: onde mora a economia de RAM

Se a queixa é espaço e memória, o culpado provável é o Docker Desktop. Ele sobe uma VM Linux que reserva uma fatia grande de memória e nem sempre devolve ao macOS. O OrbStack aloca memória sob demanda e libera de volta quando os containers ficam ociosos.

Um benchmark publicado em 2026 em um MacBook Pro M2 com 16 GB mediu o Docker Desktop ocupando mais de 4 GB sem nenhum container rodando, contra menos de 1 GB do OrbStack. A pressão de memória do sistema ficou no vermelho com Docker Desktop e no verde com OrbStack. Os números exatos variam por máquina, mas a ordem de grandeza bate com a experiência de quem migrou.

A migração é simples: brew install orbstack, aceitar a importação dos dados do Docker Desktop, e seus docker e docker compose continuam funcionando igual. Um detalhe: o OrbStack é gratuito para uso pessoal, mas uso comercial exige o plano pago. Confira antes de adotar no trabalho.

Quando o compose completo vale a pena

O setup híbrido não é dogma. Containerizar tudo faz sentido quando:

  • o time é grande ou tem rotatividade, e o tempo de onboarding importa mais que a performance individual;
  • há dependências nativas difíceis, como versões específicas de libvips, ImageMagick ou clientes de banco proprietários;
  • a app depende de muitos serviços vizinhos, como Elasticsearch, LocalStack ou outros microsserviços.

Nesses casos, prefira um devcontainer em vez de um compose feito à mão. O Rails gera a configuração com rails new --devcontainer, e editores como VS Code e RubyMine abrem o projeto direto dentro do container. Rodando sobre OrbStack, o custo de I/O cai bastante em relação ao Docker Desktop.

Bônus: talvez você nem precise do Redis

Em apps Rails 8, o Solid Queue vem configurado por padrão e guarda a fila no próprio banco. Em desenvolvimento, você pode rodar os jobs dentro do Puma com SOLID_QUEUE_IN_PUMA=1 ou como processo separado via bin/jobs no Procfile. Resultado: um container a menos e um processo a menos.

O tradeoff é real. Sidekiq ainda entrega mais throughput em cargas pesadas de jobs, e muitas apps já usam Redis para cache ou Action Cable. Para um projeto novo ou de tráfego moderado, porém, começar só com Postgres simplifica muito o ambiente.

Resumo da decisão

CenárioRecomendação
Dev solo ou time pequeno no MacHíbrido: app nativa, Postgres e Redis no compose, OrbStack
Um único projeto, sem preocupação com versãoPostgres e Redis via Homebrew
Time grande, onboarding frequenteDevcontainer
Dependências nativas complicadasDevcontainer ou compose completo
App nova em Rails 8Híbrido com Solid Queue, sem Redis

O objetivo do ambiente local é encurtar o ciclo entre salvar o arquivo e ver o resultado. Rodar a app nativa e containerizar só o que tem estado entrega isso sem abrir mão da paridade com produção.

Fontes

  1. PostgreSQL FAQ: versão atual e calendário de releases www.postgresql.org
  2. PostgreSQL 19 Beta 4 Released www.postgresql.org
  3. OrbStack vs Docker Desktop (2026): Benchmarks, Pricing, and Who Should Switch thepromptshelf.dev
  4. Solid Queue (rails/solid_queue) github.com
  5. Pacote redis no Alpine Linux (licença AGPL-3.0 ou SSPL-1.0) pkgs.alpinelinux.org

Perguntas frequentes

Rodar Rails dentro do Docker no Mac é mais lento?

Sim, principalmente por causa do bind mount entre o sistema de arquivos do macOS e a VM Linux. Boot, reload de código e watchers de assets sentem esse custo. Runtimes como OrbStack reduzem a diferença, mas Ruby nativo continua mais rápido.

Por que não instalar Postgres direto pelo Homebrew?

Funciona e é o mais leve, mas dificulta manter a mesma versão de produção e isolar projetos que usam versões diferentes. Com container, cada projeto fixa sua própria versão.

Preciso de Redis em um projeto Rails 8?

Não obrigatoriamente. O Solid Queue usa o banco de dados para a fila de jobs e vem configurado por padrão no Rails 8. Redis continua útil para Sidekiq em cargas pesadas, cache e Action Cable.

Qual versão do Postgres usar no compose?

A mesma major do seu banco em produção. Em outubro de 2026, a versão estável mais recente é o PostgreSQL 18, com o 19 ainda em beta.

Comentários

Faça login com GitHub para comentar.

Ainda não há comentários.