
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.
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 -ve 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ário | Recomendação |
|---|---|
| Dev solo ou time pequeno no Mac | Híbrido: app nativa, Postgres e Redis no compose, OrbStack |
| Um único projeto, sem preocupação com versão | Postgres e Redis via Homebrew |
| Time grande, onboarding frequente | Devcontainer |
| Dependências nativas complicadas | Devcontainer ou compose completo |
| App nova em Rails 8 | Hí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
- PostgreSQL FAQ: versão atual e calendário de releases www.postgresql.org
- PostgreSQL 19 Beta 4 Released www.postgresql.org
- OrbStack vs Docker Desktop (2026): Benchmarks, Pricing, and Who Should Switch thepromptshelf.dev
- Solid Queue (rails/solid_queue) github.com
- 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.