spring-boot-admin-docs/src/site/docs/09-samples/30-sample-eureka.md
The Eureka sample demonstrates Spring Boot Admin Server integration with Netflix Eureka service discovery. This sample shows how to automatically discover and monitor Spring Boot applications registered with Eureka without using the Admin Client.
Location: spring-boot-admin-samples/spring-boot-admin-sample-eureka/
Features:
graph TD
ES[Eureka Server
Port 8761] -->|Service Registry| AS[Admin Server
Port 8080]
ES -->|Service Registry| MA[Monitored Apps]
Key Points:
# Using Docker
docker run -d -p 8761:8761 springcloud/eureka
# Or using Spring Cloud Eureka server JAR
java -jar eureka-server.jar
Verify Eureka is running: http://localhost:8761
cd spring-boot-admin-samples/spring-boot-admin-sample-eureka
mvn spring-boot:run
Access Admin UI at: http://localhost:8080
cd spring-boot-admin-samples/spring-boot-admin-sample-eureka
docker-compose up
This starts:
Access Points:
http://localhost:8080http://localhost:8761http://localhost:8888http://localhost:80mvn spring-boot:run -Dspring-boot.run.arguments=\
--eureka.client.serviceUrl.defaultZone=http://other-eureka:8761/eureka/
Or set environment variable:
export EUREKA_SERVICE_URL=http://other-eureka:8761
mvn spring-boot:run
<dependencies>
<!-- Admin Server -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<!-- Eureka Discovery Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Web (Servlet excluded, uses WebFlux) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Note: Tomcat is excluded, so this sample runs on Netty (reactive stack).
@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient // Enable Eureka discovery
@EnableAdminServer // Enable Admin Server
public class SpringBootAdminEurekaApplication {
private final AdminServerProperties adminServer;
public SpringBootAdminEurekaApplication(AdminServerProperties adminServer) {
this.adminServer = adminServer;
}
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminEurekaApplication.class, args);
}
}
Key Annotations:
@EnableDiscoveryClient: Enables Eureka client functionality@EnableAdminServer: Enables Admin Serverspring:
application:
name: spring-boot-admin-sample-eureka
profiles:
active:
- secure
eureka:
instance:
leaseRenewalIntervalInSeconds: 10 # Heartbeat interval
health-check-url-path: /actuator/health
metadata-map:
startup: ${random.int} # Trigger refresh on restart
client:
registryFetchIntervalSeconds: 5 # Fetch registry every 5s
serviceUrl:
defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
management:
endpoints:
web:
exposure:
include: "*" # Expose all actuator endpoints
endpoint:
health:
show-details: ALWAYS
Configuration Details:
For applications to be monitored, they only need:
spring:
application:
name: my-service # Service name in Eureka
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
metadata-map:
management.context-path: /actuator # Tell Admin where actuator is
management:
endpoints:
web:
exposure:
include: "*" # Expose endpoints
No Admin Client dependency needed!
@Bean
@Profile("insecure")
public SecurityWebFilterChain securityWebFilterChainPermitAll(
ServerHttpSecurity http) {
return http
.authorizeExchange((authorizeExchange) ->
authorizeExchange.anyExchange().permitAll())
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.build();
}
@Bean
@Profile("secure")
public SecurityWebFilterChain securityWebFilterChainSecure(
ServerHttpSecurity http) {
return http
.authorizeExchange((authorizeExchange) ->
authorizeExchange
.pathMatchers(adminServer.path("/assets/**"))
.permitAll()
.pathMatchers("/actuator/health/**")
.permitAll()
.pathMatchers(adminServer.path("/login"))
.permitAll()
.anyExchange()
.authenticated())
.formLogin((formLogin) -> formLogin
.loginPage(adminServer.path("/login"))
.authenticationSuccessHandler(loginSuccessHandler(...)))
.logout((logout) -> logout
.logoutUrl(adminServer.path("/logout"))
.logoutSuccessHandler(logoutSuccessHandler(...)))
.httpBasic(Customizer.withDefaults())
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.build();
}
The docker-compose.yml provides a complete microservices environment:
version: '2'
services:
# Eureka Server
eureka:
image: springcloud/eureka
container_name: eureka
ports:
- "8761:8761"
environment:
- EUREKA_INSTANCE_PREFERIPADDRESS=true
# Admin Server
admin:
build:
context: .
dockerfile: ./src/main/docker/Dockerfile
depends_on:
- eureka
ports:
- "8080:8080"
environment:
- EUREKA_SERVICE_URL=http://eureka:8761
- EUREKA_INSTANCE_PREFER_IP_ADDRESS=true
# Spring Cloud Config Server
config:
image: springcloud/configserver
depends_on:
- eureka
ports:
- "8888:8888"
environment:
- EUREKA_SERVICE_URL=http://eureka:8761
# Sample Microservices
customers:
image: springcloud/customers
depends_on:
- config
- rabbit
environment:
- CONFIG_SERVER_URI=http://config:8888
- RABBITMQ_HOST=rabbit
stores:
image: springcloud/stores
depends_on:
- config
- rabbit
- mongodb
environment:
- CONFIG_SERVER_URI=http://config:8888
- RABBITMQ_HOST=rabbit
- MONGODB_HOST=mongodb
# Infrastructure
mongodb:
image: tutum/mongodb
ports:
- "27017:27017"
environment:
- AUTH=no
rabbit:
image: "rabbitmq:4"
ports:
- "5672:5672"
docker-compose up
docker-compose down
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f admin
Application Startup:
Admin Server Discovery:
Health Monitoring:
Application Shutdown:
Admin Server reads specific metadata keys:
eureka:
instance:
metadata-map:
# Required for proper endpoint detection
management.context-path: /actuator
management.port: 8081 # If different from service port
# Optional - for authenticated actuators
user.name: admin
user.password: ${admin.password}
# Optional - custom metadata
startup: ${random.int} # Triggers refresh
environment: production
version: ${project.version}
Important Keys:
management.context-path: Where actuator endpoints are locatedmanagement.port: If management port differs from application portuser.name / user.password: Credentials for secured actuatorsstartup: Random value forces Admin to refresh endpoints after restarthttp://localhost:8761SPRING-BOOT-ADMIN-SAMPLE-EUREKAhttp://localhost:8080# Start another instance
SERVER_PORT=8081 mvn spring-boot:run
Within 5 seconds, it should appear in Admin UI.
Stop the application (Ctrl+C). Within ~40 seconds (lease timeout), it should disappear from Admin UI.
Stop a monitored service and watch status change from UP → DOWN in Admin UI.
Filter which services to monitor:
spring:
boot:
admin:
discovery:
ignored-services:
- eureka-server # Don't monitor Eureka itself
- config-server # Don't monitor Config Server
Group services using metadata:
# Client application
eureka:
instance:
metadata-map:
group: backend-services
team: platform
If client actuators are secured:
# Client application
eureka:
instance:
metadata-map:
user.name: actuator-admin
user.password: ${actuator.password}
Admin Server automatically uses these credentials.
eureka:
instance:
health-check-url-path: /custom/health
metadata-map:
management.context-path: /custom
| Aspect | Eureka Discovery | Direct Registration |
|---|---|---|
| Setup | Eureka Server required | No additional infrastructure |
| Client Dependency | Only Eureka client | Admin Client required |
| Discovery | Automatic | Manual configuration |
| Scalability | Excellent (100+ services) | Limited (static config) |
| Dynamic Updates | Automatic | Manual restart |
| Use Case | Microservices | Monoliths, small deployments |
| Complexity | Higher | Lower |
Check Eureka connectivity:
# Test Eureka API
curl http://localhost:8761/eureka/apps
# Check Admin logs
docker-compose logs admin | grep -i eureka
Common Issues:
Solution:
# Verify configuration
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/ # Trailing slash!
Check health endpoint:
curl http://localhost:8080/actuator/health
Verify metadata:
eureka:
instance:
metadata-map:
management.context-path: /actuator # Must match actual path
Services take too long to appear:
eureka:
client:
registryFetchIntervalSeconds: 5 # Reduce from default 30s
instance:
leaseRenewalIntervalInSeconds: 10 # Reduce from default 30s
Port conflicts:
# Change ports in docker-compose.yml
ports:
- "9090:8080" # Map to different host port
Container connectivity:
# Check network
docker network inspect spring-boot-admin-sample-eureka_discovery
# Check container logs
docker-compose logs eureka
Run multiple Eureka servers:
eureka:
client:
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka2:8761/eureka/
Secure Eureka communication:
eureka:
client:
serviceUrl:
defaultZone: https://${eureka.user}:${eureka.password}@eureka:8761/eureka/
Optimize for large deployments:
spring:
boot:
admin:
monitor:
period: 20000 # Increase polling interval (ms)
connect-timeout: 5000
read-timeout: 10000
eureka:
client:
registryFetchIntervalSeconds: 10 # Balance freshness vs. load
Register Admin Server with itself:
spring:
boot:
admin:
discovery:
ignored-services: [] # Don't ignore any services
This sample demonstrates:
✅ Service Discovery Integration
✅ Dynamic Monitoring
✅ Complete Setup
✅ Scalable Architecture