Introduction
Welcome! This guide will walk you through a real-world microservices application - a TODO app that demonstrates how different services written in different programming languages can work together seamlessly. If you're new to DevOps or microservices, don't worry - I'll explain everything step by step!
Repository: HNG DevOps on GitHub
What You'll Learn:
- How microservices architecture works in practice
- How to use Docker to containerize multiple services
- How to set up Traefik as a reverse proxy
- How different programming languages work together
- How services communicate with each other
- How to implement authentication across microservices
What is a Microservices Architecture?
The Traditional Way (Monolithic)
Imagine building a house where everything - kitchen, bedroom, bathroom - is one giant room. If you want to renovate the kitchen, you might affect the bedroom too. That's a monolithic application.
The Microservices Way
Now imagine a house where each room is a separate, self-contained unit. You can renovate the kitchen without touching the bedroom. Each room has its own entrance and can be accessed independently. That's microservices architecture.
Why Microservices?
Independent Development: Different teams can work on different services
Technology Flexibility: Use the best language/framework for each service
Scalability: Scale only the services that need it
Fault Isolation: If one service fails, others keep running
Easier Maintenance: Smaller codebases are easier to understand
Project Overview
This project is a TODO application that allows users to:
- Register and log in (Authentication)
- Create, read, update, and delete TODO items
- View user profiles
- Track operations through logging
The Magic Behind It
The application is split into 5 independent microservices:
- Frontend (Vue.js) - The user interface
- Auth API (Go) - Handles user authentication
- TODOs API (Node.js) - Manages TODO items
- Users API (Java/Spring Boot) - Manages user profiles
- Log Message Processor (Python) - Processes and logs operations
Understanding the Components
Let's break down each component in simple terms:
1. Frontend (Vue.js - JavaScript)
What it does: This is what users see and interact with - the web interface.
Think of it as: The cashier at a restaurant who takes your order and brings you food.
Why Vue.js? It's a modern, lightweight JavaScript framework perfect for building interactive user interfaces.
2. Auth API (Go)
What it does: Handles user authentication and generates JWT (JSON Web Tokens) for secure access.
Think of it as: The security guard who checks your ID and gives you a badge to enter the building.
How JWT Works:
1. User logs in with username/password
2. Auth API verifies credentials
3. Auth API generates a JWT token (like a temporary pass)
4. User includes this token in future requests
5. Other services verify the token to confirm identity
Why Go? Go is fast, efficient, and excellent for building high-performance APIs.
3. TODOs API (Node.js)
What it does: Manages all TODO operations - create, read, update, delete.
Think of it as: The kitchen that prepares your food orders.
Redis Integration:
When you create or delete a TODO, the API sends a message to Redis (a message queue), which the Log Message Processor picks up and logs.
Why Node.js? Node.js is great for I/O-heavy operations and has a rich ecosystem of packages.
4. Users API (Java/Spring Boot)
What it does: Manages user profile information.
Think of it as: The HR department that maintains employee records.
Why Java/Spring Boot? Spring Boot is enterprise-grade, robust, and widely used in production environments.
5. Log Message Processor (Python)
What it does: Listens to Redis queue and logs TODO operations.
Think of it as: The security camera system that records all activities.
Why Python? Python is simple, readable, and perfect for quick scripting tasks.
6. Traefik (Reverse Proxy)
What it does: Routes incoming requests to the correct service and handles SSL/TLS certificates.
Think of it as: The receptionist who directs visitors to the right department.
Key Features:
- Automatic service discovery
- SSL/TLS certificate management (Let's Encrypt)
- HTTP to HTTPS redirection
- Path-based routing
Technology Stack
Here's a summary of all technologies used:
| Component | Technology | Purpose |
|---|---|---|
| Frontend | Vue.js | User interface |
| Auth API | Go | Authentication service |
| TODOs API | Node.js | TODO management |
| Users API | Java/Spring Boot | User profile management |
| Log Processor | Python | Logging service |
| Message Queue | Redis | Inter-service communication |
| Reverse Proxy | Traefik | Request routing & SSL |
| Containerization | Docker | Package services |
| Orchestration | Docker Compose | Manage multiple containers |
Architecture Overview
Visual Architecture
Internet
|
v
+----------------+
| Traefik |
| (Port 80/443) |
+----------------+
|
+------------------+------------------+
| | |
v v v
+----------+ +----------+ +----------+
| Frontend | | Auth API | |TODOs API |
| (Vue.js) | | (Go) | | (Node.js)|
+----------+ +----------+ +----------+
| | |
| v |
| +-------------+ |
+--------->| Users API |<-----------+
| (Java) |
+-------------+
+-------------+ +-------------+
| Log Message |<--Redis------| TODOs API |
| Processor | +-------------+
| (Python) |
+-------------+
Request Flow Example
Let's trace what happens when a user creates a TODO:
- User Action: User fills out TODO form and clicks "Create"
-
Frontend: Sends POST request to
https://example.com/api/todos - Traefik: Receives request, checks routing rules, forwards to TODOs API
-
TODOs API:
- Validates JWT token
- Creates TODO in database
- Publishes "TODO created" message to Redis
- Returns success response
- Redis: Stores message in queue
-
Log Message Processor:
- Reads message from Redis
- Logs the operation
- Frontend: Receives success response, updates UI
Setting Up the Project
Prerequisites
Before you start, make sure you have:
- Docker installed (Download here)
- Docker Compose installed (usually comes with Docker Desktop)
- Basic command line knowledge
- A text editor (VS Code, Sublime, etc.)
Step 1: Clone the Repository
git clone https://github.com/cypher682/hng13-stage-3-devops.git
cd DevOps-Stage-6
Step 2: Understand the Project Structure
DevOps-Stage-6/
├── frontend/ # Vue.js application
│ ├── Dockerfile # Instructions to build frontend container
│ └── src/ # Source code
├── auth-api/ # Go authentication service
│ ├── Dockerfile
│ └── main.go
├── todos-api/ # Node.js TODO service
│ ├── Dockerfile
│ └── server.js
├── users-api/ # Java Spring Boot service
│ ├── Dockerfile
│ └── src/
├── log-message-processor/ # Python logging service
│ ├── Dockerfile
│ └── processor.py
├── docker-compose.yml # Orchestration configuration
└── .env # Environment variables
Step 3: Configure Environment Variables
The .env file contains configuration for all services:
# User credentials (for testing)
USER1_USERNAME=user1
USER1_PASSWORD=password1
# JWT Secret (for token generation)
JWT_SECRET=myfancysecret
# Redis Configuration
REDIS_HOST=redis-queue
REDIS_PORT=6379
REDIS_CHANNEL=log_channel
Important: In production, never commit .env files with real credentials!
Step 4: Build and Run
# Build all services
docker compose build
# Start all services
docker compose up -d
# Check if all services are running
docker compose ps
What -d means: Runs containers in "detached" mode (in the background).
Step 5: Verify Services
Check that all containers are running:
docker compose ps
You should see all services with status "Up" or "Running":
- traefik
- frontend
- auth-api
- todos-api
- users-api
- log-message-processor
- redis-queue
Understanding Docker Compose
What is Docker Compose?
Docker Compose is a tool for defining and running multi-container Docker applications. Instead of running each container manually, you define everything in a docker-compose.yml file.
Key Sections Explained
1. Services Definition
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
Explanation:
-
services:- Defines all containers -
traefik:- Service name -
image:- Docker image to use -
container_name:- Name for the container -
restart:- Restart policy
2. Port Mapping
ports:
- "80:80"
- "443:443"
Format: HOST_PORT:CONTAINER_PORT
Explanation:
- Maps port 80 on your computer to port 80 in the container
- Allows you to access services from your browser
3. Networks
networks:
- app-network
Explanation:
- All services on the same network can communicate with each other
- Services can reference each other by service name (e.g.,
http://auth-api:8081)
4. Traefik Labels (Routing)
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`example.com`)"
- "traefik.http.routers.frontend.entrypoints=websecure"
Explanation:
- Tells Traefik to route requests for
example.comto this service - Enables HTTPS with automatic certificate generation
How Services Communicate
Internal Communication (Service-to-Service)
Services communicate using service names as hostnames:
// In Frontend (Vue.js)
const AUTH_API_ADDRESS = 'http://auth-api:8081';
const TODOS_API_ADDRESS = 'http://todos-api:8082';
Why this works:
- Docker Compose creates a network where services can find each other by name
- No need for IP addresses
External Communication (User-to-Service)
Users access services through Traefik:
User → https://example.com → Traefik → Frontend
User → https://example.com/api/auth → Traefik → Auth API
User → https://example.com/api/todos → Traefik → TODOs API
Authentication Flow
1. User submits login form
↓
2. Frontend sends credentials to Auth API
↓
3. Auth API verifies with Users API
↓
4. Auth API generates JWT token
↓
5. Frontend stores token
↓
6. Frontend includes token in all future requests
↓
7. Each API validates token before processing
Testing the Application
1. Access the Frontend
Open your browser and navigate to:
http://localhost:8080
2. Test Authentication
Login with test credentials:
Username: user1
Password: password1
3. Create a TODO
- Click "Add TODO"
- Enter a title and description
- Click "Save"
- Check that the TODO appears in the list
4. Check Logs
View logs from the Log Message Processor:
docker compose logs -f log-message-processor
You should see log entries for TODO creation.
5. Test API Endpoints Directly
Get all users:
curl http://localhost:8080/api/users
Login (get JWT token):
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"user1","password":"password1"}'
Common Issues and Troubleshooting
Issue 1: Containers Won't Start
Symptoms: Containers show as "Exited" or "Restarting"
Solutions:
# Check logs for specific service
docker compose logs auth-api
# Rebuild containers
docker compose down
docker compose build --no-cache
docker compose up -d
Issue 2: Port Already in Use
Error: bind: address already in use
Solutions:
# Find what's using the port (Windows)
netstat -ano | findstr :80
# Change port in docker-compose.yml
ports:
- "8000:80" # Use port 8000 instead
Issue 3: Services Can't Communicate
Symptoms: Frontend can't reach APIs
Solutions:
# Verify all services are on the same network
docker network inspect devops-stage-6_app-network
# Restart networking
docker compose down
docker compose up -d
Debugging Commands Cheat Sheet
# View all running containers
docker compose ps
# View logs for all services
docker compose logs
# View logs for specific service
docker compose logs -f frontend
# Restart specific service
docker compose restart todos-api
# Stop all services
docker compose down
# View resource usage
docker stats
Key Takeaways
What You've Learned
-
Microservices Architecture
- How to split an application into independent services
- Benefits of using different languages for different services
- How services communicate with each other
-
Docker & Containerization
- How to containerize applications
- How to use Docker Compose for multi-container applications
- How to manage container networking
-
Reverse Proxy with Traefik
- How to route requests to different services
- How to automatically manage SSL certificates
- How to use labels for service discovery
-
Inter-Service Communication
- Synchronous communication (HTTP/REST)
- Asynchronous communication (Message Queues)
- Authentication across services (JWT)
Real-World Applications
This architecture pattern is used by companies like:
- Netflix - Hundreds of microservices
- Amazon - Service-oriented architecture
- Uber - Microservices for different features
- Spotify - Independent teams, independent services
Next Steps
To deepen your understanding:
-
Modify the Application
- Add a new microservice (e.g., Comments API)
- Implement a database for persistent storage
- Add user registration functionality
-
Improve the Infrastructure
- Add monitoring with Prometheus and Grafana
- Implement centralized logging
- Add CI/CD pipeline with GitHub Actions
-
Security Enhancements
- Implement rate limiting
- Add API gateway
- Use secrets management
Additional Resources
Documentation
Tools
- Docker Desktop
- Postman - API testing
- Portainer - Docker management UI
Conclusion
Congratulations! You've just learned how to build, deploy, and manage a complete microservices application. This project demonstrates real-world DevOps practices used by major tech companies.
Remember:
- Start small - Don't try to build everything at once
- Understand each component - Know what each service does
- Experiment - Break things and fix them (that's how you learn!)
- Read logs - They're your best friend when debugging
- Keep learning - DevOps is constantly evolving
The skills you've gained here - Docker, microservices, reverse proxies, and service orchestration - are highly valuable in the industry. Keep practicing, keep building, and most importantly, keep learning!
Full Project Repository: HNG DevOps on GitHub
Top comments (0)