Introduction
As part of my DevOps learning journey with DMI, I deployed the Spring PetClinic Microservices application locally using Docker Desktop.
Spring PetClinic is a sample microservices application widely used for learning cloud-native development and DevOps practices. Instead of running as a single application, it consists of several independent services that work together, including configuration management, service discovery, API routing, monitoring, and distributed tracing.
The objective of this exercise was to deploy the entire application stack on my local machine, understand how the services interact, and gain hands-on experience troubleshooting a real microservices environment.
Prerequisites
Before starting the deployment, I installed the following tools:
Docker Desktop
Git
Java 17
Maven (for local development if needed)
Visual Studio Code
I also verified that Docker Desktop was running correctly before attempting the deployment.
Cloning the Repository
The first step was cloning the project repository.
git clone
cd spring-petclinic-microservices
Once inside the project directory, I reviewed the project structure and confirmed that the Docker Compose file was available.
dir
I located the docker-compose.yml file, which contained the definitions for all application services.
Building the Custom Images
The project included custom configurations for Prometheus and Grafana, so I built the images before starting the application.
docker compose build
The build process downloaded dependencies and created the required Docker images.
After the build completed successfully, I verified the images:
docker images
Starting the Application
To deploy the entire stack, I ran:
docker compose up -d
This command created the network and containers defined in the Compose file.
At first, everything appeared normal.
docker ps -a
However, I noticed that many containers remained in the Created state rather than transitioning to Running.
That was the first indication that something was wrong.
Troubleshooting the Startup Process
The most challenging part of the deployment was understanding why the services were not starting.
I began investigating with:
docker compose ps
and
docker logs config-server
The issue turned out to be related to service dependencies and health checks.
The application uses a startup sequence where certain services must become healthy before others can start.
Why Config Server Starts First
The Config Server acts as a central configuration repository for all microservices.
When a service starts, it first retrieves its configuration from the Config Server.
Without it, the remaining services do not know how they should be configured.
The Docker Compose file enforces this dependency through health checks and startup conditions.
During troubleshooting, I confirmed the health status using:
docker inspect config-server --format='{{json .State.Health}}'
Eventually, the Config Server reported:
Status: healthy
which allowed the next stage of the startup process to continue.
Why Discovery Server Starts Second
After the Config Server becomes available, the Discovery Server (Eureka) starts.
The Discovery Server allows services to register themselves and discover other services on the network.
Services such as:
Customers Service
Visits Service
Vets Service
API Gateway
Admin Server
all depend on Eureka to locate one another.
Without Discovery Server, service-to-service communication cannot function properly.
One interesting observation was that the Discovery Server took much longer to start than expected.
Its logs showed that initialization required over a minute before the health checks passed.
I verified its status using:
docker logs discovery-server
and
docker inspect discovery-server --format='{{json .State.Health}}'
Once both Config Server and Discovery Server became healthy, the rest of the services were able to start.
Verifying the Deployment
After the startup sequence completed, I verified the deployment by accessing the exposed endpoints.
Config Server
http://localhost:8888
Eureka Dashboard
http://localhost:8761
API Gateway
http://localhost:8080
The Eureka dashboard was particularly useful because it showed registered services and confirmed that service discovery was working correctly.
Exploring the Observability Stack
One of the most interesting parts of the deployment was exploring the monitoring and tracing tools included with the project.
Prometheus
Prometheus was responsible for collecting application metrics.
I accessed it through:
Prometheus provided visibility into application performance and service metrics.
Grafana
Grafana was available at:
Using Grafana dashboards, I could visualize the metrics collected by Prometheus and observe how the services behaved during runtime.
Zipkin
Zipkin was available at:
This was probably my favorite part of the deployment.
After generating traffic through the application, I could see traces showing requests moving between services.
Instead of simply seeing whether a service was running, Zipkin showed how requests flowed through the microservices architecture and how long each step took.
It provided a practical demonstration of distributed tracing and helped me better understand how modern microservices are monitored in production environments.
Key Lessons Learned
The biggest lesson from this deployment was that creating containers successfully does not necessarily mean the application is running correctly.
Most of the time spent on the deployment involved understanding service dependencies, reviewing logs, and checking health status.
I also learned the importance of:
Docker health checks
Service startup order
Troubleshooting with container logs
Understanding microservice dependencies
Monitoring and observability tools
Working through these issues gave me a much deeper understanding of how containerized applications operate compared to simply reading about them.
Conclusion
Deploying the Spring PetClinic Microservices application locally provided valuable hands-on experience with Docker, microservices, service discovery, monitoring, and troubleshooting.
While the deployment was not completely smooth, the challenges were actually the most valuable part of the exercise. Investigating why services failed to start and understanding how the application components depended on one another helped reinforce key DevOps concepts in a practical way.
This project was completed as part of my learning journey with DMI.
DMI Cohort 3 Registration:
https://docs.google.com/forms/d/e/1FAIpQLSel7ai7nyb0P1qLW4vEyfB_nEsD4lUF1XG88vmAaFGBOb6hPA/viewform
Top comments (0)