Skip to main content

Command Palette

Search for a command to run...

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.

Updated
6 min read
One Command. Eight Microservices. Countless Lessons: My Spring PetClinic Deployment Journey
Q
Cloud & DevOps Engineer sharing practical insights on AWS, Kubernetes, Terraform, Docker, CI/CD, and modern cloud infrastructure.

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