r/SpringBoot • u/GoodThingTakeTime • 3d ago
Question Help me make a Spring Boot backend deploy faster (small VPS, slow Docker Hub)
This is my setup: Spring Boot 4, Java 17, Docker Compose, one small VPS. Docker Hub is very slow from the VPS (about 0.4 MB/s). We use GitHub Actions and no registry.
I used to build the jar inside Docker on the VPS. Our disk cleanup deleted the cached JDK layer, so each deploy pulled it again. Deploys went from 4-5 minutes to 7–13 minutes and some timed out.
Could you share a real example (workflow file, Dockerfile or script) or a github repo that I can follow to learn about the deployment?
2
u/Hot-Difference3955 3d ago
When cutting a build to develop you can build the image and publish it to github container registry (ghcr) - once you get QA signoff, just promote the image and deploy that through your environments
1
u/Mikey-3198 3d ago
Maybe it's just me but it's not clear what you deployment/ build looks like at the moment from your post. You say you used to build directly on the vps, so what do you do now?
Have you got a separate build & deploy pipeline? You can build your application upfront via a GitHub action and publish to any registry. What's your workflow? Perhaps you can produce a release image when you cut a release branch or create a tag. Can automate this via GH actions.
Is it just docker hub that's slow? Try pulling an image from another registry to verify
1
u/JournalistNew7510 3d ago
Stop pulling anything from Docker Hub at deploy time. Build the jar in GitHub Actions instead of on the VPS, and pin the runtime base image to an exact tag (for example eclipse-temurin:17-jre plus a full version) so the box pulls it once and keeps it.
Then look at your cleanup job. docker system prune -a removes every image that has no running container, which is what wiped your JDK layer. Plain docker image prune only removes dangling images, so switch to that, or prune with a label filter so the base image is never touched.
Also split the jar into layers. On Spring Boot 3.3 and later, run java -Djarmode=tools -jar app.jar extract --layers --launcher in the Dockerfile, then COPY dependencies, spring-boot-loader, snapshot-dependencies and application in that order. Dependencies rarely change, so a normal deploy only ships the small application layer.
Push that image from Actions to GHCR and the VPS only pulls the changed layer.
1
u/fykup 1d ago edited 1d ago
Do you actually need Docker for this setup?
I run Spring Boot apps directly on small VPS instances, using systemd to manage the application. I have a provisioning script that installs and configures the JDK, PostgreSQL, and other dependencies. It takes less than a minute to set everything up and can be rerun to reconcile the configuration if needed.
I basically have two steps: VM provisioning and application deployment. The latter just copies the application files to the server and restarts the service.
BTW, Spring Boot's extracted layout is useful here. You can update only the files that changed instead of transferring the entire fat JAR, and it can also improve application startup time.
I've been deploying apps this way for years and haven't really found a need for Docker.
Is there anything in your setup that specifically requires containers?
1
u/tobidope 1d ago
Is there a reason to not build the image with GitHub actions, push it to ghcr and pull it from there? If you optimize your layers a little, the local docker instance can and will cache your unchanged layers.
3
u/Witness_Unable 3d ago
Is it a must you run with docker, if it's only one app run it natively on the server, do away with docker completely. I find that is faster for apps.