Spring Boot on Minikube: Local Kubernetes Development Guide
Learn to run Spring Boot apps on Minikube for local Kubernetes development.
20+ years shipping production Java in banking & fintech. Everything here is grounded in real deployments.
- ✓Java 17+ and Maven 3.9+ installed
- ✓Docker Desktop 24+ or equivalent
- ✓Minikube v1.32+ and kubectl installed
- ✓Basic Kubernetes knowledge (pods, services, deployments)
- ✓Spring Boot 3.2.x project with a REST API
• Set up Minikube locally with Spring Boot 3.2.x • Dockerize your app with multi-stage builds for efficiency • Deploy to Minikube using kubectl and YAML manifests • Debug with port-forwarding and live logs • Use Minikube addons like ingress and dashboard for full local dev experience
Think of Minikube as a mini Kubernetes cluster that runs on your laptop, like a model train set for testing real-world railway operations. Spring Boot is the engine, and Minikube is the track—you build and test locally before going to production.
Running Spring Boot applications in Kubernetes is the gold standard for modern microservices deployment. But developing locally against a real cluster has historically been painful—you either pay for cloud resources or deal with heavyweight local setups. Minikube changes that. It gives you a single-node Kubernetes cluster that runs in a VM or container on your machine, perfect for local development and testing. In this guide, we'll walk through deploying a Spring Boot 3.2.x application to Minikube. You'll learn how to create a Docker image, write Kubernetes manifests, and debug issues that pop up when your app runs in a containerized environment. This isn't just a tutorial—it's a collection of hard-won lessons from running Spring Boot in production clusters. We'll cover common pitfalls like container image sizing, health checks, and configuration management. By the end, you'll have a repeatable workflow for local Kubernetes development that mirrors production behavior. This is the setup I've used at three different SaaS companies, and it's saved countless hours of 'works on my machine' debugging. Let's get into it.
Setting Up Your Spring Boot Project for Minikube
Before we touch Minikube, your Spring Boot app needs to be container-ready. I'm assuming you have a standard Spring Boot 3.2.x application with a REST controller—something like a simple payment endpoint. The first step is adding the Spring Boot Maven plugin for building an executable JAR. Use Java 17 or 21 for compatibility. Your pom.xml should have the spring-boot-maven-plugin configured with a finalName to avoid version suffixes. Make sure your application.properties doesn't hardcode ports—use server.port=${PORT:8080} so Kubernetes can override it. Also, add management endpoints for health checks: spring-boot-starter-actuator. This is non-negotiable for Kubernetes liveness and readiness probes. I've seen too many apps fail because they didn't expose /actuator/health. Here's the minimal setup:
What the Official Docs Won't Tell You
The official Spring Boot Kubernetes guide assumes you have a production cluster ready. They don't tell you that Minikube has quirks that will bite you. First, Minikube's default Docker daemon is separate from your host's Docker. If you build images with your local Docker, Minikube can't see them unless you run 'eval $(minikube docker-env)' or push to a registry. Second, resource limits matter locally—Minikube runs on your machine, so a Spring Boot app with default heap settings (like 2GB) can starve your laptop. Set -Xmx256m in your Dockerfile. Third, Minikube's storage class is 'standard' but slow. If your app uses JPA with Hibernate, initial schema creation can timeout. I once spent three hours debugging 'PodInitializing' because Hibernate took 90 seconds to validate 50 tables. The fix: add 'spring.jpa.properties.hibernate.boot.allow_jdbc_metadata_access=false' and set 'spring.jpa.hibernate.ddl-auto=validate' instead of 'create'. Finally, Minikube's default service type is ClusterIP—you can't access it from your browser without port-forwarding. Don't be that person who changes it to LoadBalancer and wonders why it doesn't work.
Dockerizing Your Spring Boot App for Minikube
Now let's build and containerize. First, ensure Minikube is running: 'minikube start --cpus=4 --memory=8192'. I recommend 4 CPUs and 8GB RAM for a decent local experience. Then point your shell to Minikube's Docker: 'eval $(minikube docker-env)'. Build your Spring Boot JAR with Maven: 'mvn clean package -DskipTests'. Then build the Docker image: 'docker build -t payment-service:v1 .'. Verify it's available: 'docker images | grep payment-service'. If you see it, Minikube can use it. Important: Never use the 'latest' tag locally—it causes confusion when you rebuild. Use semantic versions. Also, if your app uses a database (like MySQL via Testcontainers in dev), you'll need to run it as a Minikube pod or service. For simplicity, I'll assume an in-memory H2 database for this example. The Dockerfile above uses a multi-stage build with a JRE base image. This is critical: the full JDK is 400MB+, while the JRE is ~180MB. In a microservice setup, those 200MB differences add up across 50 services. I've seen teams run out of disk on Minikube because they used JDK images. Don't be that team.
Writing Kubernetes Manifests for Spring Boot
With the image ready, we need Kubernetes manifests. Create a 'k8s' directory in your project root. Start with a Deployment YAML. Key fields: replicas (1 is fine for local), selector matchLabels, template metadata labels, and container spec. Set resource requests and limits—this is where most local dev setups fail. If you don't set limits, Minikube will let your pod consume all CPU, choking other services. For a Spring Boot app with -Xmx256m, set memory limit to 512MB (leave headroom). CPU limit at 500m (half a core). Add liveness and readiness probes using the actuator endpoint. The readiness probe is especially important—without it, Kubernetes sends traffic to your pod before Spring Boot has finished initializing. I've debugged 'Connection Refused' errors for hours because of this. Also, set 'terminationGracePeriodSeconds: 30' to give Spring Boot time to shut down gracefully. Then a Service manifest to expose the app internally. Use ClusterIP type—we'll access it via port-forwarding.
Deploying to Minikube and Debugging
Deploy your manifests: 'kubectl apply -f k8s/'. Check pod status: 'kubectl get pods'. If it shows 'Running', great. If 'CrashLoopBackOff' or 'Pending', debug immediately. Common issues: image not found (run 'eval $(minikube docker-env)' and rebuild), resource limits too low (check 'kubectl describe pod'), or health probe failing (check logs with 'kubectl logs <pod-name>'). For the first time, watch logs in real-time: 'kubectl logs -f deployment/payment-service'. You should see Spring Boot starting. If it hangs, check if Hibernate is timing out (see Section 2). Once running, access the app via port-forwarding: 'kubectl port-forward service/payment-service 8080:8080'. Then curl http://localhost:8080/actuator/health. You should get a 200 OK. If you get a 404, your actuator endpoints might be misconfigured. Add 'management.endpoints.web.exposure.include=health,info' to application.properties. Also, enable the Minikube dashboard for a visual overview: 'minikube dashboard'. This opens a browser UI showing pods, services, and events. I use it constantly to spot resource issues.
Configuration Management with ConfigMaps and Secrets
Hardcoding configuration in application.properties is a recipe for disaster. In Kubernetes, use ConfigMaps for non-sensitive config and Secrets for sensitive data. For Spring Boot, you can mount these as files or inject them as environment variables. I prefer environment variables because they're easier to override. Create a ConfigMap for your app properties: 'kubectl create configmap payment-config --from-literal=spring.datasource.url=jdbc:h2:mem:testdb'. For secrets (like API keys), use: 'kubectl create secret generic payment-secrets --from-literal=api-key=supersecret'. Then reference them in your Deployment YAML under 'env'. Spring Boot automatically maps environment variables to properties (e.g., SPRING_DATASOURCE_URL becomes spring.datasource.url). This is a lifesaver. Also, consider using Spring Cloud Kubernetes for dynamic config reload, but that's overkill for Minikube. Keep it simple: mount ConfigMaps as env vars. One gotcha: if you change a ConfigMap, pods won't automatically reload. You need to restart the deployment: 'kubectl rollout restart deployment/payment-service'. I've seen teams waste hours wondering why config changes didn't take effect. Don't be that team.
Using Minikube Addons for a Better Dev Experience
Minikube comes with addons that make local development feel more like a real cluster. Enable the ones you need: 'minikube addons enable ingress' for HTTP routing, 'minikube addons enable metrics-server' for resource monitoring, and 'minikube addons enable dashboard' (already covered). The ingress addon is especially useful if you want to test with a real domain locally. Create an Ingress resource that routes to your service. You'll need to add an entry to your /etc/hosts file pointing to Minikube's IP (get it with 'minikube ip'). For example: '192.168.49.2 payment.local'. Then curl http://payment.local/actuator/health. This simulates production traffic patterns. Another addon: 'ingress-dns' for automatic DNS resolution on macOS/Linux. Also enable 'registry' addon if you want a local Docker registry. But for most local dev, the basic addons are enough. One pro tip: if you're using a database like PostgreSQL, deploy it as a StatefulSet with a PersistentVolumeClaim. Minikube supports hostPath volumes, so data persists across pod restarts. I've used this pattern for local development of a billing system—it's far better than an in-memory database.
Troubleshooting Common Minikube Issues
Even with the best setup, things go wrong. Here's my battle-tested troubleshooting guide. Issue 1: 'Pod stuck in Pending'. This usually means insufficient resources. Run 'kubectl describe pod <name>' and check Events. If it says '0/1 nodes are available: insufficient cpu', scale down or increase Minikube resources. You can't change resources after start—delete and recreate with 'minikube delete && minikube start --cpus=8 --memory=12288'. Issue 2: 'ImagePullBackOff'. This means Kubernetes can't find the image. Did you run 'eval $(minikube docker-env)' before building? Check 'docker images' inside Minikube's context. If the image is missing, rebuild. Issue 3: 'CrashLoopBackOff'. The app is starting but crashing. Get logs: 'kubectl logs <pod-name> --previous' to see the last crash. Common causes: missing env vars, port conflicts, or Hibernate connection issues. Issue 4: 'Connection refused' when port-forwarding. Your app might not be ready yet. Wait for the pod to show 'Running' and check logs. Also verify the port in your container spec matches your app's port. Issue 5: Minikube itself crashes. This happens when your laptop runs out of memory. Monitor with 'minikube status' and 'docker stats'. I've had to 'minikube delete' and start fresh more times than I care to admit.
The Case of the Vanishing Pod: Image Pull Backoff in Staging
- Always use multi-stage Docker builds for Spring Boot apps.
- Monitor image sizes—anything over 500MB is a red flag for microservices.
- Test deployments locally with Minikube before pushing to staging.
eval $(minikube docker-env) && docker build -t payment-service:v1 .kubectl rollout restart deployment/payment-service| File | Command / Code | Purpose |
|---|---|---|
| pom.xml (excerpt) | Setting Up Your Spring Boot Project for Minikube | |
| Dockerfile | FROM eclipse-temurin:17-jre-alpine AS runtime | What the Official Docs Won't Tell You |
| Terminal commands | minikube start --cpus=4 --memory=8192 | Dockerizing Your Spring Boot App for Minikube |
| k8s | apiVersion: apps/v1 | Writing Kubernetes Manifests for Spring Boot |
| Terminal commands | kubectl apply -f k8s/ | Deploying to Minikube and Debugging |
| k8s | spec: | Configuration Management with ConfigMaps and Secrets |
| k8s | apiVersion: networking.k8s.io/v1 | Using Minikube Addons for a Better Dev Experience |
| Troubleshooting commands | kubectl describe pod | Troubleshooting Common Minikube Issues |
Key takeaways
Interview Questions on This Topic
How would you configure health probes for a Spring Boot application in Kubernetes?
Frequently Asked Questions
20+ years shipping production Java in banking & fintech. Everything here is grounded in real deployments.
That's Spring Boot. Mark it forged?
5 min read · try the examples if you haven't