<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Osman Ali</title>
    <description>The latest articles on DEV Community by Osman Ali (@osman_ali_54da64a0b9cc49a).</description>
    <link>https://dev.to/osman_ali_54da64a0b9cc49a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4014280%2Fe7e0b62f-5e43-407c-a963-c1b915896b02.jpg</url>
      <title>DEV Community: Osman Ali</title>
      <link>https://dev.to/osman_ali_54da64a0b9cc49a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/osman_ali_54da64a0b9cc49a"/>
    <language>en</language>
    <item>
      <title>Running 8 Microservices Locally with One Command — A DevOps Engineer's Guide to Spring PetClinic</title>
      <dc:creator>Osman Ali</dc:creator>
      <pubDate>Sat, 04 Jul 2026 01:26:10 +0000</pubDate>
      <link>https://dev.to/osman_ali_54da64a0b9cc49a/running-8-microservices-locally-with-one-command-a-devops-engineers-guide-to-spring-petclinic-569c</link>
      <guid>https://dev.to/osman_ali_54da64a0b9cc49a/running-8-microservices-locally-with-one-command-a-devops-engineers-guide-to-spring-petclinic-569c</guid>
      <description>&lt;p&gt;Introduction&lt;br&gt;
Spring PetClinic is a well-known sample application built with Spring Boot and Spring Cloud. What makes it interesting from a DevOps perspective is that it is not a single application — it is a distributed system made up of 8 separate microservices that all need to work together. Each service has its own responsibility, its own port, and its own dependencies.&lt;br&gt;
As part of my DMI Cohort 2 final project, I deployed the full Spring PetClinic Microservices stack locally on my Ubuntu Linux machine using Docker Compose. In this post I will walk you through exactly how I did it, what broke along the way, and what the observability stack showed me once everything was running.&lt;/p&gt;

&lt;p&gt;Prerequisites&lt;br&gt;
Before starting, make sure you have the following installed on your machine:&lt;/p&gt;

&lt;p&gt;Docker — version 29.6.1 or later. Verify with: docker --version&lt;br&gt;
Docker Compose — included with modern Docker installations&lt;br&gt;
Git — to clone the repository&lt;br&gt;
A stable internet connection — the config-server fetches configuration from GitHub on startup&lt;/p&gt;

&lt;p&gt;Step 1 — Clone the Repository&lt;br&gt;
git clone &lt;a href="https://github.com/ossyzali/spring-petclinic-microservices.git" rel="noopener noreferrer"&gt;https://github.com/ossyzali/spring-petclinic-microservices.git&lt;/a&gt;&lt;br&gt;
cd spring-petclinic-microservices&lt;br&gt;
Verify the contents:&lt;br&gt;
ls spring-petclinic-microservices&lt;br&gt;
You should see folders for each microservice — spring-petclinic-api-gateway, spring-petclinic-customers-service, spring-petclinic-vets-service, spring-petclinic-visits-service, and more — along with the docker-compose.yml file.&lt;/p&gt;

&lt;p&gt;Step 2 — Start Everything with One Command&lt;br&gt;
docker compose up -d&lt;br&gt;
This single command does everything — pulls all the Docker images, builds the custom Prometheus and Grafana images, creates the network, and starts all 11 containers. The -d flag runs everything in the background.&lt;br&gt;
After a few minutes verify all containers are running:&lt;br&gt;
docker compose ps&lt;br&gt;
You should see all 11 containers with status Up:&lt;br&gt;
admin-server        Up    0.0.0.0:9090-&amp;gt;9090/tcp&lt;br&gt;
api-gateway         Up    0.0.0.0:8080-&amp;gt;8080/tcp&lt;br&gt;
config-server       Up    0.0.0.0:8888-&amp;gt;8888/tcp  (healthy)&lt;br&gt;
customers-service   Up    0.0.0.0:8081-&amp;gt;8081/tcp&lt;br&gt;
discovery-server    Up    0.0.0.0:8761-&amp;gt;8761/tcp  (healthy)&lt;br&gt;
genai-service       Up    0.0.0.0:8084-&amp;gt;8084/tcp&lt;br&gt;
grafana-server      Up    0.0.0.0:3030-&amp;gt;3000/tcp&lt;br&gt;
prometheus-server   Up    0.0.0.0:9091-&amp;gt;9090/tcp&lt;br&gt;
tracing-server      Up    0.0.0.0:9411-&amp;gt;9411/tcp  (healthy)&lt;br&gt;
vets-service        Up    0.0.0.0:8083-&amp;gt;8083/tcp&lt;br&gt;
visits-service      Up    0.0.0.0:8082-&amp;gt;8082/tcp&lt;/p&gt;

&lt;p&gt;Step 3 — The Startup Order and Why It Matters&lt;br&gt;
This was the most important lesson I learned during this deployment. Not all services can start at the same time. The depends_on setting in docker-compose.yml controls the startup order.&lt;br&gt;
Config Server must start first. It holds the configuration for every other service — database settings, port numbers, application properties. Without it, every other service has nothing to read its settings from and crashes immediately on startup.&lt;br&gt;
Discovery Server must start second. It is the Eureka service registry. Every microservice registers itself with Eureka when it starts so they can find each other on the network. Without it, services cannot communicate.&lt;br&gt;
I experienced this first-hand. My discovery-server kept crashing with a ConfigClientFailFastException because my internet connection was unstable and config-server was slow to fetch its configuration from GitHub. The fix was to wait until config-server showed a healthy status and then restart discovery-server manually:&lt;br&gt;
docker compose up -d discovery-server&lt;br&gt;
Once discovery-server was healthy, all the remaining 6 services started without any issues.&lt;/p&gt;

&lt;p&gt;Step 4 — Verify the Application&lt;br&gt;
Open each URL in your browser to confirm everything is running:&lt;br&gt;
ServiceURLSpring PetClinic Apphttp://localhost:8080Eureka Dashboardhttp://localhost:8761Spring Boot Adminhttp://localhost:9090Zipkin Tracinghttp://localhost:9411Prometheushttp://localhost:9091Grafanahttp://localhost:3030&lt;br&gt;
The PetClinic app should show the welcome page with the Find Owners, Register Owner, and Veterinarians menu. Test it by clicking Find Owners, adding a visit to a pet, and browsing the vets list to confirm the full application is working end to end.&lt;/p&gt;

&lt;p&gt;Step 5 — The Observability Stack&lt;br&gt;
This was the most exciting part of the deployment. Three tools give you complete visibility into what the application is doing:&lt;br&gt;
Prometheus scrapes metrics from every microservice every 15 seconds. Open the Targets page at &lt;a href="http://localhost:9091/targets" rel="noopener noreferrer"&gt;http://localhost:9091/targets&lt;/a&gt; to see all services being monitored. Run this query in the Expression bar to see live request counts:&lt;br&gt;
http_server_requests_seconds_count&lt;br&gt;
The graph shows climbing lines for each service — proof that real traffic is flowing through the system.&lt;br&gt;
Grafana turns all that Prometheus data into visual dashboards. Open &lt;a href="http://localhost:3030" rel="noopener noreferrer"&gt;http://localhost:3030&lt;/a&gt; and navigate to the Spring PetClinic Metrics dashboard. You can see HTTP Request Latency, HTTP Request Activity, and business metrics like Owners Created and Visits Created — all updating in real time.&lt;br&gt;
Zipkin gives you distributed tracing. But here is something important — Zipkin tracing is not enabled by default in the Docker Compose setup. I had to add two environment variables to all 5 microservice definitions in docker-compose.yml:&lt;br&gt;
yamlenvironment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MANAGEMENT_ZIPKIN_TRACING_ENDPOINT=&lt;a href="http://tracing-server:9411/api/v2/spans" rel="noopener noreferrer"&gt;http://tracing-server:9411/api/v2/spans&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MANAGEMENT_TRACING_SAMPLING_PROBABILITY=1.0
After restarting the services with docker compose up -d --force-recreate, Zipkin immediately started showing live traces. I could see individual requests travelling through api-gateway, customers-service, visits-service, and vets-service — with the exact time each hop took. This is the same fix I had applied to our production AKS Helm charts on May 20th during the team project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 6 — Clean Up&lt;br&gt;
When you are done, stop and remove all containers with:&lt;br&gt;
docker compose down&lt;br&gt;
This stops every container and removes the network cleanly. Your images remain so the next startup is faster.&lt;/p&gt;

&lt;p&gt;Key Takeaway&lt;br&gt;
The biggest lesson from this deployment was understanding that microservices are not just about splitting an application into smaller pieces — they require careful orchestration. The startup order, service discovery, configuration management, and observability all need to be in place before you can say the system is truly running. Docker Compose makes it possible to experience all of this locally before touching a cloud environment.&lt;/p&gt;

&lt;p&gt;About DMI&lt;br&gt;
This deployment was completed as part of the DMI Micro-Internship Cohort 2, run by Pravin Mishra through CloudAdvisory Oy. DMI gives you real hands-on DevOps experience working in a team on production-grade infrastructure. If you want to build skills like this, join the DMI Cohort 4 waiting list here:&lt;br&gt;
&lt;a href="https://forms.gle/B5FqjrVryqxZ5UrX7" rel="noopener noreferrer"&gt;https://forms.gle/B5FqjrVryqxZ5UrX7&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>microservices</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
