Fazendo deploy de Spring Boot: por que um Dockerfile é a resposta certa, não um fallback
O Rails tem uma convenção de servidor web, o Django tem o gunicorn, o Laravel tem o Octane ou o PHP-FPM — cada ecossistema convergiu pra um conjunto pequeno e adivinhável de jeitos de de fato iniciar um processo web. O mundo da JVM nunca fez isso do mesmo jeito: uma aplicação Spring Boot pode ser um jar puro, um WAR no Tomcat, construída com Maven ou Gradle, iniciada com meia dúzia de formatos de comando razoáveis dependendo de como o projeto está estruturado. Chutar o errado aqui não falha de forma óbvia — falha de um jeito que parece um problema da aplicação em vez da detecção.
Por que Dockerfile primeiro é a escolha honesta aqui
Em vez de fingir que consegue auto-detectar um comando de build e run da JVM que é genuinamente ambíguo entre projetos, um repositório com o próprio Dockerfile é o verdadeiro método de build de primeira escolha no Railyard — checado antes do Railpack, antes do Nixpacks, antes de qualquer outra coisa. Pro Spring Boot especificamente, isso não é uma funcionalidade faltando pra contornar; é a ferramenta correta pra um formato de build que tem respostas válidas demais pra chutar com segurança. Um Dockerfile diz exatamente qual versão de JDK, qual ferramenta de build, e qual comando de run final a aplicação precisa — informação que nenhum scanner de pom.xml ou build.gradle sozinho consegue inferir de forma confiável.
FROM eclipse-temurin:21-jre
COPY target/my-app.jar app.jar
ENV SERVER_PORT=$PORT
CMD ["java", "-jar", "app.jar"]
A única exigência real: a aplicação precisa se vincular à $PORT (o Spring Boot lê isso de SERVER_PORT ou server.port), o mesmo contrato que todo método de build na plataforma espera.
O que continua funcionando do mesmo jeito que qualquer outra aplicação
- Configuração e secrets: qualquer coisa lida via
@Valueou a sintaxe${VAR}doapplication.propertiesé uma variável de ambiente simples em Variables, ou definida comrailyard env:set my-app KEY=VALUE— nunca embutida na imagem, então o mesmo build roda sem mudanças do staging até a produção. - Bancos de dados: aponte a aplicação pra um addon Postgres ou MySQL a partir do canvas e conecte a connection string dele no
application.propertiescomo uma variável — o addon em si é provisionado do mesmo jeito independente da linguagem. - Deploy no push: uma vez que o Dockerfile constrói localmente,
git push(ourailyard create my-app https://github.com/me/my-app) reconstrói e faz o deploy de novo em cada push, igual a qualquer outro repositório.
O tradeoff real, dito de forma clara
Isso significa um pouco mais de trabalho inicial do que um repositório Rails ou Django recebe de graça — escrever o Dockerfile uma vez, em vez de ele ser inferido. Em troca, o build se comporta exatamente do jeito que o Dockerfile diz que vai se comportar, toda vez, o que pra um build de JVM vale mais do que uma conveniência que teria chutado errado numa porcentagem real dos projetos.
Referência completa: Build methods, Deploy a Docker image.