A complete DevOps project featuring a FastAPI application with a live system metrics dashboard, infrastructure provisioning with Terraform, automated configuration with Ansible, and containerization with Docker.
- Overview
- Architecture
- Prerequisites
- Quick Start
- Local Development
- Docker
- Infrastructure Deployment
- API Reference
- Testing
- Makefile Commands
- Project Structure
- Contributing
- License
This project is a DevOps learning sandbox that demonstrates modern infrastructure and deployment practices. The application itself, a simple system metrics API, serves as a minimal but functional payload for the pipeline.
| Practice | Tool | Description |
|---|---|---|
| Infrastructure as Code | Terraform | Automated AWS provisioning |
| Configuration Management | Ansible | Zero-touch server setup |
| Containerization | Docker | Multi-stage builds for optimized images |
| CI/CD | GitHub Actions | Lint, test, build, and deploy pipeline |
| Monitoring | Gradio + Plotly | Real-time metrics dashboard |
┌─────────────────────────────────────────────────────────────────────────┐
│ GitHub Actions │
│ (Lint → Test → Build → Deploy) │
└─────────────────────┬───────────────────────────────────────────────────┘
│
▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Terraform │────▶│ Ansible │────▶│ Application │
│ (AWS EC2, SG) │ │ (Docker, Config) │ │ (FastAPI) │
└──────────────────┘ └──────────────────┘ └──────────────────┘
- Python 3.11+
- uv - Fast Python package manager
- Docker - For containerization
- Terraform - For infrastructure provisioning
- Ansible - For configuration management
- AWS CLI - Configured with appropriate credentials
# Clone the repository
git clone git@github.com:lele-sf/fastapi-devops-pipeline.git
cd fastapi-devops-pipeline
# Install dependencies
uv sync
# Run the application
uv run uvicorn src.app.main:app --reloadOpen your browser:
- API: http://localhost:8000
- Docs: http://localhost:8000/docs
- Dashboard: http://localhost:8000/dashboard
# Install all dependencies (including dev)
uv sync
# Install pre-commit hooks
uv run pre-commit install
# Activate the virtual environment (optional, uv run handles this)
source .venv/bin/activate # Linux/macOS
# or
.venv\Scripts\activate # Windows# Development mode with auto-reload
uv run uvicorn src.app.main:app --reload
# Or using FastAPI CLI
uv run fastapi dev src/app/main.py# Build the image
docker build -t fastapi-devops-pipeline .
# Run the container
docker run -p 8000:80 fastapi-devops-pipelinedocker run -p 8000:80 <your-dockerhub-username>/fastapi-devops-pipeline:latestAccess the application at http://localhost:8000
cd infrastructure/terraform
# Copy the example file
cp terraform.tfvars.example terraform.tfvars
# Edit with your values
# - my_public_ip: Your IP in CIDR notation (e.g., "203.0.113.1/32")
# - ssh_public_key_path: Path to your SSH public keycd infrastructure/ansible
# Copy the example file
cp inventory-example.ini inventory.ini
# The deploy script will update the IP automatically# Make the script executable
chmod +x scripts/deploy.sh
# Run full deployment
./scripts/deploy.shThe deployment script will:
- ✅ Provision AWS infrastructure with Terraform
- ✅ Retrieve the EC2 public IP
- ✅ Update Ansible inventory
- ✅ Wait for SSH availability
- ✅ Configure the server with Ansible
- ✅ Deploy the application in Docker
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Welcome message |
/health |
GET | Health check endpoint |
/metrics |
GET | System metrics (CPU, memory, uptime) |
/dashboard |
GET | Interactive Gradio dashboard |
/docs |
GET | OpenAPI documentation (Swagger UI) |
/redoc |
GET | OpenAPI documentation (ReDoc) |
{
"uptime_seconds": 3600.25,
"memory_used_mb": 512.45,
"memory_total_mb": 2048.00,
"cpu_percent": 15.5,
"system": "Linux",
"architecture": ["64bit", "ELF"],
"timestamp": "2025-01-15T10:30:00+00:00"
}# Run all tests
uv run pytest
# Run with verbose output
uv run pytest -v
# Run with coverage
uv run pytest --cov=src/app
# Linting
uv run ruff check src/
# Format code
uv run ruff format src/
# Run pre-commit checks manually
uv run pre-commit run --all-filesRun make help to see all available commands:
make install # Install production dependencies
make install-dev # Install dev dependencies + pre-commit hooks
make test # Run tests
make test-cov # Run tests with coverage
make lint # Check code with ruff
make format # Format code with ruff
make run # Run FastAPI locally
make docker-build # Build Docker image
make docker-run # Run Docker container
make deploy # Full infrastructure deployment
make pre-commit # Run pre-commit hooks
make clean # Remove cache filesfastapi-devops-pipeline/
├── .github/
│ └── workflows/
│ └── ci-cd.yaml # CI/CD pipeline configuration
├── infrastructure/
│ ├── ansible/
│ │ ├── inventory.ini # Server inventory (gitignored)
│ │ ├── inventory-example.ini
│ │ ├── playbook.yaml # Configuration playbook
│ │ └── requirements.yml # Ansible collections
│ └── terraform/
│ ├── ec2.tf # EC2 instance
│ ├── key_pair.tf # SSH key pair
│ ├── main.tf # Provider configuration
│ ├── outputs.tf # Output values
│ ├── security_group.tf # Security group rules
│ ├── variables.tf # Variable definitions
│ └── terraform.tfvars.example
├── scripts/
│ └── deploy.sh # Full deployment script
├── src/
│ └── app/
│ ├── __init__.py
│ ├── main.py # FastAPI application entry
│ ├── routes.py # API routes
│ ├── schemas.py # Pydantic models
│ └── dashboard.py # Gradio dashboard
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Pytest fixtures
│ └── test_routes.py # API endpoint tests
├── .gitignore
├── .pre-commit-config.yaml # Pre-commit hooks
├── .python-version
├── Dockerfile # Multi-stage Docker build
├── LICENSE
├── Makefile # Development commands
├── pyproject.toml # Project dependencies
├── uv.lock # Locked dependencies
└── README.md
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Ensure all pre-commit hooks pass (
uv run pre-commit run --all-files) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Note: Pre-commit hooks will automatically run on every commit. If any hook fails, the commit will be rejected and you'll need to fix the issues before committing again.
This project is licensed under the MIT License - see the LICENSE file for details.