One Command. Eight Microservices. Countless Lessons: My Spring PetClinic Deployment Journey
What started as a simple local deployment became one of the most valuable lessons of my DevOps journey, teaching me how microservices, observability, and modern cloud-native applications actually work.

A few weeks ago, I typed a command I had used many times before:
docker compose up -d
Seconds later, containers began appearing on my screen.
But this wasn’t a simple web application.
Behind that single command were eight microservices, a configuration server, service discovery, distributed tracing, monitoring dashboards, and an entire cloud-native architecture running on my laptop.
That was the moment I realized I wasn’t just starting containers.
I was getting a front-row seat to how modern applications actually work.
Before my team deployed Spring PetClinic Microservices on AWS EKS as part of our DevOps Micro-Internship (DMI) capstone project, I wanted to understand the application from the ground up. So I decided to deploy it locally on my machine.
What started as a personal learning exercise quickly became one of the most valuable DevOps lessons I’ve had so far.
What is Spring PetClinic?
Spring PetClinic is one of the most popular reference applications in the Spring ecosystem.
Unlike traditional monolithic applications, the microservices version is built using multiple independent services that work together to deliver a complete application experience.
The platform consists of:
Config Server
Discovery Server
API Gateway
Customers Service
Vets Service
Visits Service
Admin Server
GenAI Service
In addition to the application services, it includes an observability stack powered by:
Prometheus
Grafana
Zipkin
This makes it an excellent project for learning cloud-native architecture, microservices communication, observability, and deployment workflows.
Prerequisites
Before getting started, I installed the following tools:
Docker Desktop
Docker Desktop provides the container runtime needed to run all application services locally.
Verify installation:
docker --version
Git
Git was used to clone the source code repository.
Verify installation:
git --version
Once both tools were installed, I was ready to begin.
Step 1: Clone the Repository
The first step was cloning the project repository.
git clone https://github.com/spring-petclinic/spring-petclinic-microservices.git cd spring-petclinic-microservices
After exploring the repository, I immediately noticed something interesting.
Unlike a monolithic application where everything lives in one place, each service had its own responsibility, configuration, and dependencies.
This was my first reminder that microservices bring both flexibility and complexity.
Step 2: Build the Docker Images
Before launching the platform, I needed to build the Docker images.
./mvnw clean install -P buildDocker
This step compiled all services and created the Docker images required for deployment.
The first build took a while because Maven downloaded dependencies and built multiple projects.
Once completed successfully, all images were available locally.
Step 3: Start the Entire Platform
Now came the exciting part.
I launched everything with a single command:
docker compose up -d
Watching dozens of containers start was surprisingly satisfying.
But what fascinated me most was what happened behind the scenes.
Docker Compose wasn’t simply starting containers.
It was orchestrating dependencies and ensuring services started in the correct order.
Why Startup Order Matters
One of the biggest lessons I learned was that not every service can start at the same time.
In a microservices architecture, some services depend on others to function correctly.
Config Server Starts First
The Config Server acts as the central source of configuration.
Before any service can run, it needs access to configuration data.
Without the Config Server, the remaining services wouldn’t know how to initialize themselves.
Discovery Server Starts Second
Once the configuration is available, the Discovery Server comes online.
This service acts as a registry where applications register themselves and discover other services.
Think of it as the directory that helps services find one another.
Business Services Start Next
With configuration and service discovery available, services such as Customers, Vets, Visits, Admin, and GenAI can start successfully.
API Gateway Starts Last
The API Gateway sits at the front of the application and routes requests to backend services.
Starting it before the other services would create communication failures.
Understanding this startup sequence gave me a much deeper appreciation for how distributed systems work.
Verifying Everything Was Running
After deployment, I verified the containers using:
docker ps
and
docker compose ps
Seeing all services in a healthy state was one of those small but rewarding moments every engineer appreciates.
The application wasn’t just deployed.
It was alive.
The Observability Stack Changed My Perspective
If there was one part of the project that completely changed how I think about applications, it was the observability stack.
Before this deployment, monitoring was something I understood in theory.
This was the first time I experienced it in practice.
Prometheus
Prometheus collected metrics from running services.
It showed valuable information such as:
Application health
Request counts
Service performance
Resource consumption
Instead of guessing how the system was behaving, I could see the data.
Grafana
Grafana transformed those metrics into dashboards that were easy to understand.
I could monitor:
CPU utilization
Memory usage
Service uptime
Application activity
Watching real-time metrics update on screen felt like looking under the hood of the application.
Zipkin
Zipkin was the tool that impressed me the most.
It allowed me to trace requests as they traveled across multiple services.
For the first time, I could visualize how one user request moved through the API Gateway, reached backend services, processed data, and returned a response.
It made the invisible visible.
And that’s when microservices finally clicked for me.
My Biggest Takeaway
Going into this project, I thought deploying applications was mainly about containers and commands.
I couldn’t have been more wrong.
What I learned is that successful deployments depend on much more than running software.
They depend on:
Configuration management
Service discovery
Dependency management
Monitoring
Observability
Distributed tracing
The application itself is only one part of the story.
The ecosystem surrounding it is what keeps it running reliably.
Final Thoughts
This local deployment became the foundation for everything that followed in my DevOps journey.
It helped me understand concepts that later became essential when working on larger cloud-native projects and Kubernetes deployments.
Sometimes the most important lessons don’t happen in production environments.
Sometimes they happen on your laptop, one container at a time.
About DMI
This project was completed as part of the DevOps Micro-Internship (DMI), a hands-on program designed to help aspiring DevOps engineers gain practical experience through real-world projects.
If you’re interested in learning DevOps, Cloud Engineering, Kubernetes, Docker, Terraform, GitOps, and AWS by actually building projects, DMI Cohort 3 is now open for registration.
👉 Register here: https://docs.google.com/forms/d/e/1FAIpQLSel7ai7nyb0P1qLW4vEyfB\_nEsD4lUF1XG88vmAaFGBOb6hPA/viewform

