Tirando uma aplicação Rails do Heroku
O motivo pelo qual a maioria das equipes fica numa plataforma gerenciada mais tempo do que pretendia não é o preço. É que a migração parece um projeto sem fim claro. Este post é o caminho mais curto que conhecemos, na ordem que mantém a aplicação rodando em cada etapa.
Passo 1: faça o deploy sem mudar nada, com buildpacks
Não comece escrevendo um Dockerfile. Comece provando que a aplicação roda em outro lugar, ponto final.
Os Cloud Native Buildpacks leem o seu repositório do mesmo jeito que o build do Heroku lê, usando camadas de runtime pré-compiladas em vez de compilar uma linguagem a partir do zero. Na prática, uma aplicação Rails ou Django padrão faz o build sem um único arquivo ser alterado.
Se ela subir, você já provou a parte difícil: nada na sua aplicação de fato dependia da plataforma.
Passo 2: mova os serviços de dados
A sua aplicação quase certamente precisa de Postgres e Redis. Provisione eles como addons, e a Railyard injeta as connection strings no ambiente do mesmo jeito que você já está acostumado.
Duas coisas pra checar:
- Extensões. Se você usa
pgvector, PostGIS ou algo parecido, confirme que o Postgres provisionado tem suporte a elas. O nosso tem, pra pgvector. - O dump. Restaure um dump real de produção no banco de dados novo antes do cutover, e cronometre. Essa é a etapa que as equipes subestimam.
Passo 3: declare seus processos
Se a sua aplicação tem um Procfile, a Railyard o lê — processo web, processo worker, e o
hook release: que roda as migrations antes de qualquer coisa servir tráfego. Esse último ponto importa
mais do que parece: é o que impede uma migration de rodar contra uma versão do código que já
começou a receber requisições.
Passo 4: mude pra um Dockerfile, se você quiser
Depois que ela está rodando, um Dockerfile te dá reprodutibilidade e builds mais rápidos a quente. Não é obrigatório, e é bem mais fácil escrever pra uma aplicação que você já consegue fazer deploy do que pra uma que você não consegue.
Com um cache de camadas apoiado num registry, rebuilds a quente de uma aplicação Rails grande caem em torno de um minuto e meio.
O que realmente quebra
De fazer isso repetidamente, os problemas recorrentes são:
- Aplicações que trazem a própria infraestrutura. Algumas aplicações sobem o ambiente inteiro
durante o
assets:precompilee precisam que um cluster de busca exista. Isso falha em qualquer plataforma sem o addon — não é um problema de migração, é um requisito da aplicação que você tinha esquecido. - Memória de build em máquinas pequenas. Um servidor de 2 GB compilando extensões nativas pode ficar sem memória. Ou você faz o build num builder dedicado, ou limita a memória do build pra ele falhar de forma limpa em vez de levar a máquina junto.
- Disco efêmero assumido. Qualquer coisa que escreve no disco local precisa de um volume persistente, ou o próximo deploy descarta isso silenciosamente.
O que você tem no final
A sua aplicação roda em servidores numa região que você escolheu, no preço do seu provedor sem markup, e se você algum dia parar de pagar pelo control plane, os containers continuam servindo tráfego. O workflow continua o mesmo de onde você saiu: push, acompanhar o build, fazer rollback se der errado.