As part of my DevOps Micro Internship (DMI), I completed the deployment of the Spring Petclinic Microservices application using Docker Compose. This project provided hands-on experience with containerization, service discovery, centralized configuration, and modern observability tools used in production-grade microservice architectures.
Unlike a traditional monolithic application, Spring Petclinic is composed of several independent microservices that communicate through an API Gateway while using centralized configuration and service discovery. Deploying such an environment helped me understand how modern cloud-native applications are built, deployed, monitored, and managed.
What I Deployed
The deployment consisted of the following services:
Config Server
Discovery Server (Netflix Eureka)
API Gateway
Customers Service
Visits Service
Vets Service
Spring Boot Admin Server
Zipkin Tracing Server
Prometheus
Grafana
All services were deployed locally using Docker Compose.
Prerequisites
Before starting the deployment, I installed the following tools:
Docker Desktop
Docker Compose
Git
Java 17
Maven
VS Code
Step 1 — Clone the Repository
The first step was cloning my GitHub repository.
git clone https://github.com/Nicest12/spring-petclinic-microservices.git
cd spring-petclinic-microservices
Step 2 — Start the Application
The entire microservices environment was started using a single command:
docker compose up -d
Docker Compose automatically created the network and started each container in the correct order.
Step 3 — Verify the Deployment
After deployment completed successfully, I verified the running containers.
docker compose ps
The output confirmed that every required service was running successfully.
I also verified the application by opening:
The Spring Petclinic home page loaded successfully, confirming that the API Gateway was routing requests correctly to the backend microservices.
Why Config Server and Discovery Server Start First
One of the most interesting lessons I learned during this deployment was the startup sequence.
The Config Server starts first because every microservice retrieves its external configuration from it during startup.
After the Config Server becomes healthy, the Discovery Server (Eureka) starts. Each microservice then registers itself with Eureka, allowing services to discover and communicate with one another dynamically instead of relying on fixed IP addresses.
Only after these two foundational services are available do the remaining services—including the API Gateway and business services—start successfully.
This startup dependency highlights the importance of centralized configuration and service discovery in a microservices architecture.
Monitoring and Observability
One of my favorite parts of the project was working with the observability stack.
Prometheus
Prometheus continuously collected metrics from the running microservices.
Using PromQL queries such as:
up
I confirmed that all monitored services were healthy and actively exposing metrics.
Grafana
Grafana was connected to Prometheus as its data source and provided visual dashboards displaying live application metrics.
Through Grafana, I could monitor service health, JVM metrics, CPU usage, memory consumption, and application performance in real time.
Zipkin
Zipkin provided distributed tracing for the application.
By generating requests through the Petclinic application, I was able to observe traces flowing through multiple microservices, making it much easier to understand request paths and identify potential performance bottlenecks.
This gave me practical experience with distributed tracing—an essential capability in cloud-native systems.
Challenges and Lessons Learned
This project taught me that deploying microservices involves much more than simply running containers.
Throughout the deployment, I encountered configuration issues, startup dependencies, and observability challenges that required careful troubleshooting. Resolving these issues improved my understanding of Docker Compose, Spring Cloud Config, Eureka Service Discovery, API Gateway routing, and monitoring tools.
One of the biggest lessons I learned is that observability is just as important as deployment. Having Prometheus, Grafana, and Zipkin available made it significantly easier to verify application health and understand how the services interacted.
Final Thoughts
Completing this deployment strengthened my confidence in working with modern DevOps tools and cloud-native applications. It demonstrated how multiple microservices can be orchestrated using Docker Compose while leveraging centralized configuration, service discovery, monitoring, and distributed tracing.
This project is part of my participation in the DevOps Micro Internship (DMI), where I continue building practical DevOps skills through real-world engineering projects.
If you're interested in gaining hands-on experience with DevOps, Cloud, Docker, Kubernetes, Infrastructure as Code, and CI/CD, I highly recommend joining the next cohort.
DMI Cohort 3 Registration:
https://docs.google.com/forms/d/e/1FAIpQLSel7ai7nyb0P1qLW4vEyfB_nEsD4lUF1XG88vmAaFGBOb6hPA/viewform
Top comments (0)