A small FastAPI service that shows a production-style delivery path: tested code, a hardened Docker image, Kubernetes manifests with health probes, and a CI pipeline.
app/main.py FastAPI app (GET / and GET /health)
tests/test_main.py pytest tests
requirements.txt Runtime dependencies (FastAPI, Uvicorn)
requirements-dev.txt Test dependencies (pytest, httpx)
Dockerfile Container image, runs as non-root user (UID 10001)
k8s/deployment.yaml Deployment: 2 replicas, probes, resource limits
k8s/service.yaml ClusterIP Service (port 80 -> 8000)
.github/workflows/ci.yml Runs the tests, then builds and smoke-tests the image
| Method | Path | Response (HTTP 200) |
|---|---|---|
| GET | / |
{"service": "InfraPilot", "version": "1.0.0", "message": "Welcome to InfraPilot"} |
| GET | /health |
{"status": "healthy", "timestamp": "<UTC ISO-8601>"} |
Unknown paths return HTTP 404. Interactive API docs are served at /docs.
Requires Python 3.12.
python -m venv .venv
# Windows (PowerShell):
.venv\Scripts\Activate.ps1
# macOS / Linux:
source .venv/bin/activate
pip install -r requirements-dev.txtpytest -vuvicorn app.main:app --reload --port 8000Then open http://localhost:8000/ and http://localhost:8000/health.
docker build -t infrapilot:1.0.0 .
docker run --rm -p 8000:8000 infrapilot:1.0.0Security notes:
- The container runs as the non-root user
appuser(UID 10001). - A
HEALTHCHECKpolls/healthevery 30 seconds. .dockerignorekeeps tests, git history, and local virtual environments out of the image.
These steps assume a local cluster such as minikube or kind:
# Make the local image available to the cluster
minikube image load infrapilot:1.0.0 # or: kind load docker-image infrapilot:1.0.0
kubectl apply -f k8s/
kubectl get pods -l app=infrapilot
kubectl port-forward service/infrapilot 8080:80
curl http://localhost:8080/healthWhat the Deployment configures:
- Readiness probe on
/health: a pod receives traffic only once it responds. - Liveness probe on
/health: Kubernetes restarts the container after 3 failed checks. - Resource requests/limits: 100m CPU / 128Mi requested, capped at 500m CPU / 256Mi.
- Security context: non-root, read-only root filesystem, no privilege escalation, all Linux capabilities dropped.
.github/workflows/ci.yml runs on every push to main and on every pull request:
- test: installs dependencies on Python 3.12 and runs
pytest. - docker-build: runs only if the tests pass. It builds the image, starts a container, checks that
/healthresponds, and confirms the container is not running as root.