DevOps Notes App is a small full-stack note-taking project built to demonstrate modern deployment workflows. The main focus of the project was learning how to ship an application with Docker, CI/CD pipelines, and Kubernetes-based self-hosting while keeping the app itself simple and easy to understand.
The application consists of a FastAPI backend with a SQLite database and a lightweight browser frontend served by Nginx. Notes can be created, listed, and deleted through a minimal UI.
This repository was created as a hands-on DevOps exercise. The goals were to:
- build and containerize a full-stack application
- practice Docker-based local development and production packaging
- automate image builds with GitHub Actions
- publish images to a container registry
- prepare the project for Kubernetes-based hosting on a remote machine or cluster
- Create notes from the browser UI
- View all saved notes
- Delete notes individually
- FastAPI backend with automatic API documentation
- SQLite persistence for simple local state
- Separate frontend and backend Docker images
- CI pipeline that builds and pushes images to GitHub Container Registry
The project uses a simple two-tier layout:
- Frontend: static HTML and JavaScript served by Nginx
- Backend: FastAPI application exposed on port 8000
- Database: SQLite file stored in a Docker volume
The frontend calls the backend API directly from the browser. The backend exposes a small REST API for note management and a health check endpoint.
- FastAPI
- Uvicorn
- SQLAlchemy
- Pydantic
- SQLite
- Docker
- Docker Compose
- GitHub Actions
- Nginx
The backend exposes the following endpoints:
- GET /health - health check
- GET /notes - list all notes
- POST /notes - create a new note
- DELETE /notes/{note_id} - delete a note by id
.
├── backend
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app
│ ├── database.py
│ ├── main.py
│ ├── models.py
│ └── schemas.py
├── frontend
│ ├── Dockerfile
│ ├── index.html
│ └── src
│ └── app.js
├── docker-compose.yml
├── docker-compose.prod.yml
└── .github
└── workflows
└── ci.yml
Add your images here to show the app in action.
- Docker
- Docker Compose
-
Build and start the services:
docker compose up --build
-
Open the frontend in your browser:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- Health check: http://localhost:8000/health
-
Stop the stack when you are done:
docker compose down
The repository also includes a production-oriented Compose file that is designed for container deployment:
docker compose -f docker-compose.prod.yml up --build -dThis version is intended to run the services without local bind mounts and keeps the database in a named volume.
The development Compose file mounts the backend source code and the frontend static files so changes are easy to test during development.
- Backend container runs Uvicorn with reload enabled
- Frontend container serves the static files through Nginx
- SQLite data is persisted in the
db-datavolume
If you want to point the frontend at a different backend host, update the API URL in frontend/src/app.js.
The backend image installs the Python dependencies, copies the FastAPI app, and runs Uvicorn from the package entry point.
The frontend image uses Nginx to serve the HTML and JavaScript assets.
- docker-compose.yml is meant for local development
- docker-compose.prod.yml is meant for production-style deployment
GitHub Actions is configured to build and publish Docker images when changes are pushed to the master branch.
Workflow location:
The pipeline:
- Checks out the repository
- Sets up Docker Buildx
- Logs in to GitHub Container Registry
- Builds and pushes the backend image
- Builds and pushes the frontend image
Published image tags follow this pattern:
- ghcr.io/rithikreddypalla/dev/backend:latest
- ghcr.io/rithikreddypalla/dev/frontend:latest
This repository was designed with Kubernetes hosting in mind. While the current repo focuses on Docker Compose and GitHub Actions, it is a good candidate for Kubernetes manifests because it already separates the frontend, backend, and persistent storage concerns.
If you extend the project for Kubernetes, the usual next steps would be:
- create a Deployment for the backend
- create a Deployment for the frontend
- expose the services with Kubernetes Services
- move the SQLite data path to persistent storage or migrate to an external database
- configure environment-specific settings with ConfigMaps and Secrets
- Notes are stored in a SQLite database file
- The backend creates the database schema on startup
- CORS is configured for local frontend development on port 3000
Some natural next improvements for the project are:
- add Kubernetes manifests and deployment notes
- replace SQLite with PostgreSQL for a more realistic production setup
- add automated tests for the API
- add form validation and a richer frontend experience
- add environment variable support for the frontend API base URL

