Make your Python FastAPI app work seamlessly with Spring Boot ecosystem: Eureka, Config Server, Spring Boot Admin, and Prometheus.
You have a Spring Boot microservices architecture with Eureka, Config Server, Spring Boot Admin, and Prometheus monitoring. You want to add a Python service but keep everything working together. This library makes that dead simple.
✅ Eureka Service Registration - Automatic registration with heartbeat
✅ Config Server Integration - Load config from Spring Cloud Config with Eureka discovery
✅ Actuator Endpoints - /actuator/health, /actuator/info, /actuator/prometheus
✅ FastAPI Integration - Drop-in support for FastAPI apps
✅ Fail-Fast Behavior - Matches Spring Boot's startup failure handling
✅ Exponential Backoff Retry - Retry logic for Eureka and Config Server
✅ Zero Magic - Own implementation, no hidden dependencies
pip install spring-ready-pythonOptional dependencies:
# For Config Server support
pip install spring-config-client-python
# For Prometheus metrics
pip install prometheus-clientfrom spring_ready import SpringReadyApp
from fastapi import FastAPI
# Create FastAPI app
app = FastAPI()
# Add Spring integration
spring_app = SpringReadyApp(app)
spring_app.start()
# Your routes
@app.get("/")
def read_root():
return {"message": "Hello from Spring-Ready Python!"}
# Run with uvicorn
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8080)That's it. Your app now:
- Registers with Eureka
- Loads config from Config Server (discovered via Eureka)
- Exposes
/actuator/health,/actuator/info,/actuator/prometheus - Shows up in Spring Boot Admin
Set via environment variables (matching Spring Boot conventions):
# Application
SPRING_APPLICATION_NAME=my-python-service
APP_PORT=8080
SPRING_PROFILES_ACTIVE=production
# Eureka
EUREKA_SERVER_URL=http://eureka:8761/eureka/
EUREKA_INSTANCE_IP=192.168.1.100 # Optional: custom IP for registration
EUREKA_INSTANCE_HOSTNAME=my-service.example.com # Optional: custom hostname
# Config Server (optional - will be discovered from Eureka)
CONFIG_SERVER_URI=http://config-server:8888
CONFIG_SERVER_USERNAME=admin
CONFIG_SERVER_PASSWORD=secret| Variable | Description | Default | Example |
|---|---|---|---|
SPRING_APPLICATION_NAME |
Application name | python-service |
my-python-service |
APP_PORT |
Application port | 8080 |
8080 |
SPRING_PROFILES_ACTIVE |
Active profile | default |
production |
EUREKA_SERVER_URL |
Eureka server URL(s) | http://localhost:8761/eureka/ |
http://eureka:8761/eureka/ |
EUREKA_INSTANCE_IP |
Custom IP for registration | Auto-detected | 192.168.1.100 |
EUREKA_INSTANCE_HOSTNAME |
Custom hostname | Auto-detected | my-service.local |
CONFIG_SERVER_URI |
Config Server URL | Discovered from Eureka | http://config:8888 |
CONFIG_SERVER_SERVICE_ID |
Config Server service ID | CONFIG-SERVER |
CONFIG-SERVER |
CONFIG_SERVER_USERNAME |
Config Server username | None | admin |
CONFIG_SERVER_PASSWORD |
Config Server password | None | secret |
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
ENV SPRING_APPLICATION_NAME=my-service
ENV EUREKA_SERVER_URL=http://eureka:8761/eureka/
ENV SPRING_PROFILES_ACTIVE=production
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]# docker-compose.yml
services:
my-service:
build: .
environment:
- EUREKA_SERVER_URL=http://eureka:8761/eureka/
- SPRING_PROFILES_ACTIVE=production
ports:
- "8080:8080"from spring_ready import SpringReadyApp
spring_app = SpringReadyApp(app)
spring_app.start()
# Add custom health check
def check_database():
# Your database check logic
return database.is_connected()
spring_app.health_endpoint.add_check("database", check_database)# Find another service registered in Eureka
config_server_url = spring_app.service_discovery.get_service_url("CONFIG-SERVER")
# Get all instances of a service
instances = spring_app.service_discovery.get_instances("my-other-service")
for instance in instances:
print(f"Instance: {instance.base_url}")from spring_ready import SpringReadyApp
spring_app = SpringReadyApp(
app=app,
app_name="my-service",
app_port=8080,
eureka_servers=["http://eureka1:8761/eureka/", "http://eureka2:8761/eureka/"],
profile="production",
fail_fast=True,
prefer_ip_address=True
)
spring_app.start()from spring_ready import SpringReadyApp
# Specify a custom IP address for Eureka registration
# Useful in Docker/Kubernetes when you need to advertise a specific IP
spring_app = SpringReadyApp(
app=app,
app_name="my-service",
instance_ip="192.168.1.100", # Custom IP address
instance_hostname="my-service.example.com" # Optional: custom hostname
)
spring_app.start()Or via environment variables:
export EUREKA_INSTANCE_IP=192.168.1.100
export EUREKA_INSTANCE_HOSTNAME=my-service.example.com- Eureka Registration: Registers with Eureka (with retry/backoff)
- Config Discovery: Discovers Config Server from Eureka
- Config Loading: Loads configuration into
os.environ - Actuator Setup: Exposes health, info, and metrics endpoints
- Heartbeat: Starts background thread for Eureka heartbeats (every 30s)
- Stops heartbeat thread
- Deregisters from Eureka
- Clean exit
| Feature | Spring Boot | spring-ready-python |
|---|---|---|
| Fail-fast on startup | ✓ | ✓ |
| Exponential backoff retry | ✓ | ✓ |
| Eureka heartbeat (30s) | ✓ | ✓ |
| Config Server discovery | ✓ | ✓ |
| Actuator endpoints | ✓ | ✓ |
| Graceful shutdown | ✓ | ✓ |
Returns application health status:
{
"status": "UP",
"components": {
"diskSpace": {"status": "UP"},
"eureka": {"status": "UP"},
"ping": {"status": "UP"}
}
}Returns application metadata:
{
"app": {
"name": "my-python-service",
"version": "1.0.0"
},
"python": {
"version": "3.11.5",
"runtime": {
"name": "CPython",
"version": "3.11.5"
}
}
}Returns Prometheus metrics in exposition format:
# HELP python_info Python platform information
# TYPE python_info gauge
python_info{implementation="CPython",version="3.11.5"} 1.0
...
Symptom: You don't see any connection attempts to your Eureka server in logs or network monitoring.
Cause: The application is likely using the default Eureka URL (http://localhost:8761/eureka/) instead of your server.
Solution:
-
Set the environment variable (Recommended):
export EUREKA_SERVER_URL=http://10.10.0.1:8761/eureka/ python your_app.py -
Or pass it explicitly in code:
spring_app = SpringReadyApp( app, eureka_servers=["http://10.10.0.1:8761/eureka/"] )
-
Verify your configuration:
import os print(f"EUREKA_SERVER_URL: {os.getenv('EUREKA_SERVER_URL')}")
-
Check the startup logs: Look for this message:
INFO:spring_ready.core:Configured Eureka server(s): http://10.10.0.1:8761/eureka/If you see:
WARNING:spring_ready.core:Using default Eureka server URL (http://localhost:8761/eureka/)Then you need to set
EUREKA_SERVER_URL. -
Enable debug logging to see detailed registration attempts:
import logging logging.basicConfig(level=logging.DEBUG)
-
Verify network connectivity:
curl http://10.10.0.1:8761/eureka/apps
Should return XML/JSON with registered applications.
Common mistakes:
- Forgetting to set
EUREKA_SERVER_URLin Docker/Kubernetes deployments - Setting the variable in your IDE but not in the runtime environment
- Using
localhostwhen running in containers (use service names or IPs instead)
Check Eureka server is reachable:
curl http://eureka:8761/eureka/appsSet fail_fast=False to start anyway:
spring_app = SpringReadyApp(app, fail_fast=False)Ensure Config Server is registered in Eureka:
curl http://eureka:8761/eureka/apps/CONFIG-SERVEROr provide direct URL:
export CONFIG_SERVER_URI=http://config-server:8888Change the port:
spring_app = SpringReadyApp(app, app_port=8081)Or via environment:
export APP_PORT=8081| Aspect | Spring Boot | Python |
|---|---|---|
| Metrics names | jvm.memory.used |
process_virtual_memory_bytes |
| Runtime info | Java/JVM | Python/CPython |
| Config refresh | /actuator/refresh |
Not supported (restart required) |
| Auto-configuration | Annotations | Explicit initialization |
- Python 3.9+
- FastAPI
- requests
Optional:
spring-config-client-pythonfor Config Server supportprometheus-clientfor metrics
MIT
Contributions welcome! This library is intentionally simple and focused. See CONTRIBUTING.md.
// Spring Boot (Kotlin)
@SpringBootApplication
@EnableDiscoveryClient
class MyApplication
// Configuration in application.yml# Python equivalent
from spring_ready import SpringReadyApp
from fastapi import FastAPI
app = FastAPI()
spring_app = SpringReadyApp(app)
spring_app.start()
# Configuration from environment variablesNote: This library focuses on making Python apps work with existing Spring Boot infrastructure. It's not a replacement for Spring Boot itself.