Deploying Spring Petclinic Microservices with Docker Compose: A Hands-On DevOps Experience
My cloud experience includes working with core AWS services such as EC2, S3, IAM, RDS, and CloudWatch, enabling me to support secure, efficient, and cost-effective cloud architectures. I’m passionate about delivering practical, cloud-first solutions that blend software engineering principles with infrastructure reliability. I’m currently focused on advancing my career in cloud and backend engineering, with a growing interest in DevOps and infrastructure automation.
Introduction
Modern applications rarely consist of a single service. Instead, they are built as collections of independent microservices that work together to deliver functionality.
As part of my DevOps learning journey with DMI, I deployed the Spring Petclinic Microservices application using Docker Compose. The deployment included eight microservices along with an observability stack consisting of Prometheus, Grafana, and Zipkin.
The goal was not only to start the application but also to understand service discovery, centralized configuration, monitoring, and distributed tracing within a microservices environment.
What I Deployed
The deployment consisted of:
Config Server
Discovery Server (Eureka)
API Gateway
Admin Server
Customers Service
Visits Service
Vets Service
GenAI Service
In addition to the application services, the environment also included:
Prometheus
Grafana
Zipkin
Together, these components formed a complete microservices platform running locally with Docker.
Prerequisites
Before starting, I installed the following tools:
Docker Desktop
Docker Desktop provided the Docker Engine required to build and run containers.
Git
Git was used to clone the project repository.
I also ensured Docker Desktop and WSL integration were functioning correctly before deployment.
Clone the Repository
The first step was cloning the project repository.
git clone <repository-url>
cd spring-petclinic-microservices
After cloning, I verified that all project files were available locally.
Starting the Environment
The entire application stack was launched using a single command:
docker compose up -d
Docker Compose automatically:
Created the Docker network
Pulled required images
Built application images
Started containers in the correct order
The deployment process took several minutes because multiple services needed to initialize and register themselves.
Verifying Container Health
After deployment, I verified that all containers were running.
docker ps
All microservices eventually reached a healthy state.
I then accessed the various interfaces:
Eureka Discovery Server
http://localhost:8761
The Eureka dashboard confirmed that all application services had successfully registered.
Grafana
http://localhost:3000
Grafana provided visualization of application metrics collected by Prometheus.
Prometheus
http://localhost:9090
Prometheus collected metrics from the microservices and infrastructure components.
Zipkin
http://localhost:9411/zipkin
Zipkin provided distributed tracing capabilities.
Why Startup Order Matters
One of the most important concepts I learned was service startup dependency.
The Config Server and Discovery Server must start before the remaining services.
Config Server
The Config Server provides centralized configuration to the microservices.
Without it, services may fail to load required configuration values during startup.
Discovery Server
The Discovery Server allows services to register themselves and discover other services dynamically.
Without service registration, communication between services becomes difficult or impossible.
Docker Compose uses startup dependencies to ensure these foundational services are available before the remaining microservices attempt to start.
Exploring the Observability Stack
A major highlight of this deployment was the observability platform.
Prometheus
Prometheus continuously collected metrics from the application.
Examples included:
CPU usage
Memory consumption
Request statistics
Service health information
Grafana
Grafana transformed raw metrics into dashboards that were much easier to understand.
The dashboards provided visibility into:
Resource utilization
Application performance
Service availability
Zipkin
Zipkin enabled distributed tracing.
By tracing requests across multiple services, it became possible to understand request flow and identify bottlenecks or communication issues.
This demonstrated how modern engineering teams monitor complex distributed systems.
Challenges Encountered
The most challenging aspect was troubleshooting the environment after the containers had started.
Initially, Docker and WSL issues delayed deployment. Later, all services appeared healthy, but tracing data was not visible as expected.
Resolving the issue required:
Reading container logs
Investigating service communication
Validating Docker networking
Confirming service registration in Eureka
This experience reinforced an important lesson:
A running container does not automatically mean a functioning application.
Observability tools and logs remain critical for troubleshooting distributed systems.
Key Takeaways
This project provided practical experience with:
Docker Compose
Microservices architecture
Service discovery with Eureka
Centralized configuration management
Monitoring with Prometheus
Dashboard visualization with Grafana
Distributed tracing with Zipkin
Most importantly, it highlighted the operational challenges that exist beyond simply starting containers.
Understanding dependencies, service communication, observability, and troubleshooting is what transforms a deployment from "running" to "production-ready."
About DMI
This deployment was completed as part of my learning journey with DMI.
If you're interested in gaining practical experience with DevOps, AWS, Docker, Kubernetes, Terraform, CI/CD, monitoring, and cloud engineering, DMI Cohort 3 starts on 27 June.
Registration Link:
https://docs.google.com/forms/d/e/1FAIpQLSel7ai7nyb0P1qLW4vEyfB_nEsD4lUF1XG88vmAaFGBOb6hPA/viewform