Skip to content

feat: Add Docker health checks, unified Docker Compose, and Traefik reverse proxy#15

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1777560292-docker-microservices-setup
Open

feat: Add Docker health checks, unified Docker Compose, and Traefik reverse proxy#15
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1777560292-docker-microservices-setup

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Apr 30, 2026

Summary

Adds production-ready Docker infrastructure for the Spring PetClinic microservices architecture with three services orchestrated via Docker Compose and routed through a Traefik reverse proxy.

Architecture

                    ┌───────────────────┐
                    │   Traefik v2.11   │
                    │    (port 80)      │
                    └─────────┬─────────┘
                              │
              ┌───────────────┼───────────────┐
              │                               │
    ┌─────────┴─────────┐         ┌───────────┴───────────┐
    │  Angular Frontend  │         │   REST API Backend    │
    │   (nginx:8080)     │         │  (spring-boot:9966)   │
    └────────────────────┘         └───────────────────────┘

Changes

  • Dockerfile — Updated to Node 18 / nginx 1.25 (alpine), replaced broken service nginx status health check with curl-based check against /health endpoint, added custom nginx.conf for SPA routing, builds with --configuration=docker for relative API URLs
  • nginx.conf — Frontend nginx config with SPA try_files fallback, gzip compression, static asset caching, and /health endpoint
  • src/environments/environment.docker.ts — Docker-specific Angular environment using relative API URL (/petclinic/api/) so requests route through Traefik
  • angular.json — New docker build configuration that swaps in environment.docker.ts
  • traefik/traefik.yml — Traefik static config with Docker provider, ping health check, and access logging
  • docker-compose.yml — Unified compose file with:
    • reverse-proxy (Traefik v2.11) — entry point on port 80, dashboard on 8081
    • api-server (spring-petclinic-rest) — backend REST API on port 9966
    • frontend (Angular/nginx) — SPA on port 8080
    • All services have health checks with proper intervals, timeouts, and retries
    • Startup ordering via depends_on with condition: service_healthy
    • Isolated petclinic-network bridge network

How it works

  1. Traefik routes /petclinic/api/* (priority 20) → api-server:9966
  2. Traefik routes / (priority 10) → frontend:8080
  3. The Angular app uses relative API URLs so browser requests go through Traefik
  4. Services start in order: reverse-proxy → api-server → frontend

Review & Testing Checklist for Human

  • Run docker compose up --build and verify all three services start healthy (docker compose ps should show all as healthy)
  • Open http://localhost — Angular UI should load and display owners/vets data from the API
  • Open http://localhost:8081 — Traefik dashboard should show the configured routers and services
  • Verify API routing: curl http://localhost/petclinic/api/vets should return JSON vet data
  • Test SPA routing: navigate to http://localhost/owners and refresh — page should load (not 404)

Notes

  • The springcommunity/spring-petclinic-rest:latest image is used for the backend; replace with a custom image if you have a private build
  • The existing environment.ts (dev) and environment.prod.ts (prod) are unchanged — only Docker builds use the new relative URL environment
  • Traefik dashboard is exposed on port 8081 (insecure mode) — disable or add auth in production

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/17abbf031f6240b3b64ddb22226759d4


Open in Devin Review

…everse proxy

- Update Dockerfile with proper curl-based health check, Node 18, and
  custom nginx config for SPA routing
- Add environment.docker.ts with relative API URL for containerized builds
- Add angular.json 'docker' build configuration
- Create nginx.conf with SPA fallback routing and /health endpoint
- Add Traefik reverse proxy with Docker provider and ping health check
- Create docker-compose.yml with three services:
  - reverse-proxy (Traefik v2.11) on port 80
  - api-server (spring-petclinic-rest) on port 9966
  - frontend (Angular/nginx) on port 8080
- All services include health checks with proper intervals/retries
- Services use depends_on with service_healthy conditions
- Custom bridge network (petclinic-network) for inter-service communication
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 4 additional findings in Devin Review.

Open in Devin Review

Comment thread nginx.conf
Comment on lines +28 to +29
return 200 '{"status":"UP"}';
add_header Content-Type application/json;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 nginx add_header after return produces duplicate Content-Type header

In the /health location block, add_header Content-Type application/json; is placed after return 200 .... The return directive internally sets Content-Type: text/plain for text responses. The add_header directive does not replace existing headers—it appends a new one. This results in the response containing two Content-Type headers (text/plain and application/json), which is an HTTP protocol violation. Different clients may interpret this inconsistently.

The correct approach is to use default_type application/json; instead, which controls the Content-Type that return uses when generating the response.

Suggested change
return 200 '{"status":"UP"}';
add_header Content-Type application/json;
default_type application/json;
return 200 '{"status":"UP"}';
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants