A minimal REST API for task management that serves as the foundation for our Docker learning path. This API is intentionally simple to implement but comprehensive enough to demonstrate Docker networking, volumes, security, and monitoring concepts.
GET /healthResponse:
{
"status": "healthy",
"version": "1.0.0",
"timestamp": "2024-01-10T10:30:00Z",
"database": "connected"
}Purpose: Docker health checks, load balancer integration, monitoring
GET /api/tasksResponse:
{
"tasks": [
{
"id": "uuid-here",
"title": "Learn Docker",
"description": "Complete Docker fundamentals module",
"completed": false,
"created_at": "2024-01-10T10:00:00Z",
"updated_at": "2024-01-10T10:00:00Z"
}
],
"total": 1
}GET /api/tasks/{id}Response:
{
"id": "uuid-here",
"title": "Learn Docker",
"description": "Complete Docker fundamentals module",
"completed": false,
"created_at": "2024-01-10T10:00:00Z",
"updated_at": "2024-01-10T10:00:00Z"
}POST /api/tasksRequest:
{
"title": "Build monitoring stack",
"description": "Implement Prometheus and Grafana"
}Response: 201 Created
{
"id": "new-uuid",
"title": "Build monitoring stack",
"description": "Implement Prometheus and Grafana",
"completed": false,
"created_at": "2024-01-10T11:00:00Z",
"updated_at": "2024-01-10T11:00:00Z"
}PUT /api/tasks/{id}Request:
{
"title": "Build monitoring stack",
"description": "Implement Prometheus and Grafana",
"completed": true
}Response: 200 OK (returns updated task)
DELETE /api/tasks/{id}Response: 204 No Content
GET /metricsResponse: (text/plain)
# HELP tasks_total Total number of tasks
# TYPE tasks_total counter
tasks_total 42
# HELP tasks_completed_total Total number of completed tasks
# TYPE tasks_completed_total counter
tasks_completed_total 35
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",endpoint="/api/tasks",status="200"} 150
http_requests_total{method="POST",endpoint="/api/tasks",status="201"} 42
# HELP http_request_duration_seconds HTTP request latency
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.1"} 120
http_request_duration_seconds_bucket{le="0.5"} 139
http_request_duration_seconds_bucket{le="1.0"} 141
http_request_duration_seconds_count 142
CREATE TABLE tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255) NOT NULL,
description TEXT,
completed BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Add updated_at trigger (PostgreSQL)
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_tasks_updated_at BEFORE UPDATE
ON tasks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();# Database
DATABASE_URL=postgres://taskuser:taskpass@postgres:5432/taskdb
# Server
PORT=8080
HOST=0.0.0.0
# Monitoring
METRICS_ENABLED=true
METRICS_PORT=9090
# Feature flags (for exercises)
ENABLE_FILE_UPLOAD=false
ENABLE_TASK_EXPORT=falseHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1RUN useradd -m -u 1000 appuser
USER appuservolumes:
- ./exports:/app/exports # Task export feature
- ./uploads:/app/uploads # File attachment featurenetworks:
frontend: # Public-facing
backend: # Database access only- Use Spring Data JPA
- Spring Actuator for metrics
- Built-in health endpoint
- SQLAlchemy for ORM
- prometheus-client for metrics
- Built-in OpenAPI docs
- sqlx for database
- actix-web-prom for metrics
- Serde for JSON
- In-memory storage
- Health endpoint only
- Single container
- PostgreSQL integration
- Docker Compose networking
- Volume persistence
- Authentication headers (optional)
- Rate limiting
- Input validation
- Prometheus metrics
- Grafana dashboards
- Full stack deployment
services:
api:
build: .
ports:
- "8080:8080"services:
api:
build: .
ports:
- "8080:8080"
depends_on:
- postgres
environment:
# DEV ONLY: local classroom credentials for teaching Compose basics.
# In production, inject secrets through a secret manager or runtime config.
DATABASE_URL: postgres://taskuser:taskpass@postgres:5432/taskdb
networks:
- backend
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: taskuser
# DEV ONLY: simple local password for examples.
POSTGRES_PASSWORD: taskpass
POSTGRES_DB: taskdb
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
volumes:
postgres_data:
networks:
backend:services:
api:
build: .
ports:
- "8080:8080"
# ... (as above)
postgres:
image: postgres:16-alpine
# ... (as above)
prometheus:
image: prom/prometheus:latest # Classroom shortcut; pin a tested version in production.
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
networks:
- backend
- monitoring
grafana:
image: grafana/grafana:latest # Classroom shortcut; pin a tested version in production.
environment:
# DEV ONLY: default local admin password for walkthroughs.
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- monitoring
volumes:
postgres_data:
prometheus_data:
grafana_data:
networks:
backend:
monitoring:# Create a task
curl -X POST http://localhost:8080/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":"Test Docker","description":"Test the API"}'
# List tasks
curl http://localhost:8080/api/tasks
# Check health
curl http://localhost:8080/health
# View metrics
curl http://localhost:8080/metrics# Test from another container
# Classroom shortcut: pin helper image tags in production or CI for reproducible results.
docker run --rm --network docker-mastery_backend \
curlimages/curl:latest \
curl http://api:8080/health
# Test volume persistence
docker compose down
docker compose up -d
curl http://localhost:8080/api/tasks # Should still have data- Language Agnostic: Same API behavior across Java, Python, Rust
- Docker Native: Health checks, metrics, graceful shutdown
- Production Ready: Non-root, resource limits, security headers
- Educational: Simple enough to understand, complex enough to be real
This Task API provides the perfect foundation for teaching Docker concepts while building something useful!