Dockerized Expense Tracker Web Application
Dockerized Expense Tracker Web Application with PostgreSQL, Node.js, and Nginx
INTRODUCTION
Managing personal finances is essential for financial well-being, but manually tracking expenses and income can be cumbersome and error-prone. This project aims to address this challenge by developing a full-stack Expense Tracker application that allows users to efficiently monitor, record, and analyse their financial activities.
The application provides secure user authentication, enabling users to maintain personal accounts, while transaction management allows adding, editing, and deleting incomes and expenses. Users can view real-time summaries, including total income, total expenses, and account balance, along with category-wise insights to better understand spending patterns.
The backend is implemented using Node.js with Express, connected to a PostgreSQL database, ensuring reliable and persistent data storage. The frontend is designed with HTML, CSS, and JavaScript to provide an interactive and intuitive user experience. For deployment, the entire application is Dockerized, ensuring consistency across different environments, while Nginx serves as a reverse proxy, routing API requests and serving static frontend files efficiently.
A key focus of this project is containerization and Docker orchestration. Each component - frontend, backend, and database - runs in separate containers, connected via a Docker network to allow seamless communication. The PostgreSQL database uses Docker volumes to persist data across container restarts, while environment variables manage sensitive information like database credentials and JWT secrets. Docker Compose orchestrates multi-container deployment, enabling scalable and reproducible setups. This approach demonstrates not only full-stack development but also modern containerization practices, highlighting portability, scalability, and maintainability.
By combining a robust backend, a responsive frontend, and containerized deployment, this Expense Tracker provides users with a practical, reliable, and user-friendly tool for managing their finances.
OBJECTIVES OF PART 1 - Backend Creation and Dockerization
Design and Implementation of Core Backend APIs
Develop a RESTful backend using Node.js and Express.js.
Implement endpoints for transaction management (add, view, edit, delete).
Store transaction data temporarily in memory (arrays or variables) to simulate database operations.
Incorporate basic validation and error handling to ensure proper API responses.
Dockerization of Backend
Create a Dockerfile for the backend service.
Configure the container to run Node.js with all dependencies preinstalled.
Verify the containerized backend using Postman to send API requests and confirm proper functionality.
Outcome of Part 1
A working backend prototype with API endpoints for transaction management.
Containerized Node.js backend environment.
OBJECTIVES OF PART 2 - Database Integration and Frontend Creation
Database Integration
Add PostgreSQL as the persistent database for data storage.
Modify backend routes to perform CRUD operations directly on PostgreSQL.
Use environment variables for secure configuration of database credentials.
Test all database operations using Postman to ensure accurate backend responses.
Frontend Development
Create a responsive web-based frontend using HTML, CSS, and JavaScript.
Include pages for login, registration, and dashboard.
Design the dashboard to display:
Total income, expenses, and balance.
Transaction list with edit and delete features.
Summary charts for spending categories.
Dockerization of Frontend
Create a Dockerfile for the frontend and use Nginx to:
Serve static frontend files.
Proxy /api requests to the backend container.
Outcome of Part 2
Functional backend connected to a persistent PostgreSQL database.
Fully developed frontend containerized and ready for integration in Part 3.
OBJECTIVES OF PART 3 - Docker Hub Publishing, Integration, Orchestration and Final Deployment
Image Build, Tagging & Docker Hub Management
Build backend and frontend Docker images locally and verify them.
Tag images following the Docker Hub naming convention (e.g., yuvaraj015/expense-tracker-backend:v1.0.0).
Push the tagged images to Docker Hub so they are publicly available for deployment.
Compose Integration and Deployment
Create the docker-compose.yml file to pull images directly from Docker Hub instead of local builds.
Include services for backend, frontend, and postgres with proper networking and volumes.
Run the full stack using docker-compose up -d and verify smooth container orchestration.
Testing and Verification
Access the application via the web interface and confirm all features (login, transactions, analytics) work correctly.
Validate data persistence even after container restarts.
Ensure minimal setup for end-users - they only need the compose file to deploy the entire app.
Outcome of Part 3
Fully integrated, multi-container Expense Tracker with backend, frontend, and database.
All images hosted on Docker Hub for easy reuse and deployment.
One-step deployment using the Docker Compose file.
A reproducible, production-ready setup demonstrating successful container orchestration.
CONTAINER DETAILS AND THEIR FUNCTIONAL ROLES
|
Container Name |
Base Image Used |
Function |
Repository Link |
|
expense-tracker-frontend |
nginx:alpine |
Hosts the static user
interface built with HTML, CSS, and JavaScript. Serves all frontend content
and routes API requests to the backend service. |
https://hub.docker.com/r/yuvaraj015/expense-tracker-frontend |
|
expense-tracker-backend |
node:20 |
Runs the Express.js REST
API that manages authentication, expense transactions, and communicates with
the PostgreSQL database. |
|
|
expense-tracker-db |
postgres:15 |
Provides a persistent
relational database for securely storing user details and expense data. |
SOFTWARE TOOLS AND TECHNOLOGIES USED
|
Tool/Software |
Version |
Purpose/Role in the
Project |
|
Node.js |
20 |
Runtime environment for
the backend server (Express.js app). Handles API routes, authentication, and
database interaction. |
|
Express.js |
^5.1.0 |
Framework for creating
REST APIs - used for routes like /register, /login, /transactions, /summary,
etc. |
|
PostgreSQL |
15 |
Relational database used
to store user credentials and transaction data persistently. |
|
pg (Node PostgreSQL
Client) |
^8.16.3 |
Node library to connect
and query the PostgreSQL database. |
|
bcrypt |
^6.0.0 |
Library used for hashing
passwords securely before storing them in the database. |
|
jsonwebtoken (JWT) |
^9.0.2 |
Used for implementing
secure token-based authentication for users. |
|
cors |
^2.8.5 |
Enables Cross-Origin
Resource Sharing so frontend (different origin) can access backend APIs. |
|
Nginx (Alpine) |
latest (from base image) |
Used as the web server to
host the static frontend (HTML, CSS, JS) files and route traffic efficiently. |
|
Docker Desktop |
4.43.2 |
Used to build, run, and
manage Docker containers for frontend, backend, and database. |
|
Docker Engine |
28.3.2 |
Core engine used by Docker
Desktop for container management. |
|
Docker Compose |
Bundled with Docker
Desktop |
Used to orchestrate
multiple containers using a single configuration file. |
|
Docker Hub |
- |
Used to store and host
custom backend and frontend container images |
|
Postman |
11.61.6 |
Tool used to test API
endpoints (register, login, CRUD, summary) before connecting the frontend. |
|
VS Code |
1.105.1 |
Integrated development
environment used for writing code and debugging. |
|
HTML / CSS / JavaScript |
- |
Used for building the
static frontend interface, including login, register, and dashboard pages. |
|
Git & GitHub |
2.48.1.windows.1 |
Used for version control |
ARCHITECTURE OF Part 1 – Dockerized Backend Service
Description:
In Part 1 the backend was implemented and containerized using Node.js (Node:20) and Express. The backend exposed RESTful APIs for transaction CRUD, storing transaction data temporarily in memory (no persistent database in Part 1). The API endpoints were tested using Postman. The backend ran inside a Docker container (built from the backend Dockerfile) to ensure an isolated, reproducible environment.
ARCHITECTURE OF PART 2 - Persistent Storage and Frontend Containerization
Description:
Part 2 focused on extending the backend with persistent storage and introducing a dedicated frontend container. The system evolved into three independent containers, each with its own Dockerfile but not yet integrated using Docker Compose:
Backend (Node.js + Express): Handles expense management APIs such as adding, editing, and deleting transactions.
Database (PostgreSQL:15): Provides persistent data storage for user and transaction details.
Frontend (HTML/CSS/JS): A simple static user interface that interacts with the backend APIs.
Each container could be built and run individually using Docker commands. Networking and orchestration were not yet automated.
ARCHITECTURE OF PART 3 - Integration and Deployment
Description:
Part 3 represented the complete system integration and deployment phase. All three services - frontend, backend, and database - were unified under Docker Compose, enabling smooth communication, automated network creation, and persistent data volumes.
The application was fully deployable with a single command (docker compose up), making it production-ready.
OVERALL ARCHITECTURE - Dockerized Full Stack Expense Tracker
Description:
The Expense Tracker Application follows a fully containerized three-tier architecture consisting of a frontend, backend, and database, all orchestrated through Docker Compose. The frontend, developed using HTML, CSS, and JavaScript, provides an intuitive user interface that allows users to register, log in, and manage their financial transactions. The backend, built using Node.js and Express, serves as the logical layer that processes incoming requests, applies validation and business rules, and communicates with the database. The PostgreSQL database acts as the persistent storage layer, ensuring that all user and transaction data remain secure and accessible across sessions.
The entire system is containerized to ensure portability, scalability, and ease of deployment. Each service runs in an isolated Docker container, minimizing dependency conflicts and simplifying maintenance. Docker Compose manages the communication between containers through an internal network and mounts persistent volumes for reliable data storage. Additionally, the backend image is pushed to Docker Hub, enabling seamless reuse and deployment on any environment. This architecture demonstrates a complete DevOps-oriented workflow - from modular development to integration, orchestration, and cloud-ready deployment - making the application both robust and production-ready.
Data Flow:
Inputs:
Users interact with the web-based interface to perform actions such as login, registration, and transaction management.
Process:
The frontend container (Nginx) handles UI and forwards API requests to the backend.
The backend container processes logic, communicates with PostgreSQL for data operations, and returns structured responses.
Docker Compose orchestrates communication between containers through a virtual network and mounts persistent volumes for data safety.
Outputs:
Users receive dynamic responses and visual summaries on the browser interface.
Data is securely stored in PostgreSQL, remaining intact across container restarts.
Application images are available on Docker Hub for reuse, scalability, and deployment on any Docker-compatible system.
PROCEDURE - PART 1: Dockerized Backend Service
Step 1: Create the project folder
Create a new folder named expense-tracker-da1.
Open this folder in Visual Studio Code (VS Code) for development.
Step 2: Initialize Node.js project
Initialize a new Node.js project: npm init -y
This creates package.json file containing project metadata and dependencies.
Install the required framework: npm install express
This adds Express.js to handle HTTP requests and automatically generates a package-lock.json file.
Step 3: Create index.js File
Create a file named index.js and add all backend logic.
Implement REST API endpoints:
GET / - Default route to verify API response.
GET /health - Health check endpoint.
GET /transactions - Retrieve all transactions.
POST /transactions - Add new transaction.
PUT /transactions/:id - Update existing transaction.
DELETE /transactions/:id - Delete a transaction.
GET /summary - Display total income, expense, and balance.
GET /category-summary - Category-wise financial summary.
Use in-memory arrays to temporarily store transactions.
Add validation and error handling for missing or invalid inputs.
Create a Dockerfile in the project root directory to containerize the backend.
The Dockerfile should:
Use Node:20 as the base image.
Copy all project files into the container.
Install dependencies using npm install.
Expose port 5000.
Set the default command to run the server.
Step 5: Build the Docker image
docker build -t expense-tracker-backend .
Builds a Docker image named expense-tracker-backend using the Dockerfile.
Step 6: Run the container
docker run -d -p 5000:5000 --name expense-tracker-backend-da1 expense-tracker-backend
Runs the backend container in detached mode and maps container port 5000 to the host port 5000.
GET /
Purpose: Check if the API is up and running.
GET /health
Purpose: Health check endpoint to verify the server’s status.
GET /transactions (initially empty)
Purpose: Retrieve all transactions.
POST /transactions (invalid input)
Purpose: Add a transaction.
POST /transactions (valid input)
Purpose: Add a transaction.
GET /transactions (after adding)
Purpose: Retrieve all transactions.
GET /summary
Purpose: View total income, total expense, and balance.
PUT /transactions/:id (update transaction)
Purpose: Modify existing transaction.
GET /category-summary
Purpose: View category-wise total income and expenses.
DELETE /transactions/:id
Purpose: Delete a transaction.
Step 8: Stop and remove container
docker stop expense-tracker-backend-da1
docker rm expense-tracker-backend-da1
PROCEDURE - PART 2: Frontend Creation, Database Setup, and Containerization
Step 1: Creating the Project Folder Structure
Create a main directory named expense-tracker.
Inside it, create two subfolders:
backend/ - Contains Node.js server files and its Dockerfile.
frontend/ - Contains HTML, CSS, and JS files for the user interface along with its Dockerfile.
Step 2: Set Up the Backend Folder
Inside backend folder, create the following files:
index.js - Contains the Express.js backend logic and routes for transactions (add, edit, delete, view) and summaries.
db.js - Manages PostgreSQL connection using environment variables for host, user, password, and database.
init.sql - Contains SQL statements to create necessary tables for users and transactions.
package.json and package-lock.json - Holds project dependencies and metadata (like express, pg, cors, etc.).
Dockerfile - Defines instructions to build the backend image using Node:20, install dependencies, copy source code, and expose port 5000.
Step 3: Set Up the Frontend Folder
Inside frontend folder, create:
index.html - Contains login and signup UI.
dashboard.html - Displays the user’s income, expenses, and transaction history.
style.css - Styles the entire frontend UI.
script.js - Handles user login, registration, and local storage.
dashboard.js - Fetches data from the backend APIs and updates the dashboard dynamically.
config.js - Stores backend API endpoint URLs (useful when backend runs on a different container).
nginx.conf - Nginx configuration file for serving static frontend files.
Dockerfile - Builds a lightweight Nginx container to serves the frontend application.
PROCEDURE - PART 3: Integration and Deployment using Docker Compose
Step 1: Build and Tag Docker Images Locally
Navigate to the backend directory:
cd backend
docker build -t expense-tracker-backend:latest .
This command builds the Docker image for the backend API and tags it as latest.
Navigate to the frontend directory:
cd ../frontend
docker build -t expense-tracker-frontend:latest .
This builds the Docker image for the frontend service.
Step 2: Push Images to Docker Hub
Log in to Docker Hub:
docker login
Enter your Docker Hub credentials when prompted.
Tag the images with your Docker Hub username and version (v1.0.0):
docker tag expense-tracker-backend:latest yuvaraj015/expense-tracker-backend:v1.0.0
docker tag expense-tracker-frontend:latest yuvaraj015/expense-tracker-frontend:v1.0.0
This renames local image tags for proper repository upload.
Push both images:
docker push yuvaraj015/expense-tracker-backend:v1.0.0
docker push yuvaraj015/expense-tracker-frontend:v1.0.0
Each image is uploaded to your Docker Hub repository.
Verify on Docker Hub:
Visit the Docker Hub account (hub.docker.com/u/yuvaraj015) and check that both images are listed.
Step 3: Create docker-compose.yml in the Root Folder
In the project’s root directory (expense-tracker), create a new file named docker-compose.yml.
The docker-compose.yml file defines and connects three services:
db – PostgreSQL database
backend - Node.js API (uses image from Docker Hub)
frontend - Nginx UI (uses image from Docker Hub)
Key elements it should include:
image: Lines referencing your Docker Hub repositories
depends_on: Ensures backend waits for DB and frontend waits for backend
volumes: Include pgdata for PostgreSQL data persistence
Port mappings:
5432:5432 for PostgreSQL
5000:5000 for backend
80:80 for frontend
Step 4: Build and Run the Containers
docker-compose up –build
This command builds (if necessary) and runs all three containers together.
Step 5: Access the Web Application
Open your browser and navigate to: http://localhost:80
The Expense Tracker UI should appear.
Step 6: Test Functionality through the Website
Register a New User
Empty fields
Valid details: Confirm user is registered successfully.
User Login
Invalid Credentials
Valid Credentials: Ensure login success.
Transaction Management
Add Transaction
Missing Fields
Valid Transaction: Ensure successful addition.
Edit Transaction
Delete Transaction
Category-wise Summary
Step 7: Stop the Containers
docker-compose down
Stops and removes all running containers cleanly.
MODIFICATIONS DONE IN CONTAINERS AND INSTRUCTIONS FOR END USERS
Backend Container
Base image used: node:20
Modifications done:
Created index.js implementing REST API endpoints for transactions, summary, and category-wise operations.
Initially used in-memory storage, later integrated with PostgreSQL for persistent storage.
Installed dependencies (express) via package.json.
Exposed port 5000.
Dockerfile created for containerization and image pushed to Docker Hub (yuvaraj015/expense-tracker-backend:v1.0.0).
Steps for end users:
Download the project folder with docker-compose.yml.
Run docker-compose up - the backend container will automatically pull the image from Docker Hub.
No modifications needed.
Frontend Container
Base image used: nginx:alpine
Modifications done:
Added static frontend files (index.html, dashboard.html, script.js, dashboard.js, style.css, config.js).
Configured nginx.conf to serve frontend and proxy API requests to backend.
Dockerfile created and image pushed to Docker Hub (yuvaraj015/expense-tracker-frontend:v1.0.0).
Steps for end users:
Container is automatically pulled by docker-compose.
Access the web app via browser on port 80.
Database Container
Image used: postgres:15 (official)
Modifications by developer:
Added initialization script init.sql for database and tables.
Configured persistent volume for data storage.
Steps for end users:
Database container automatically starts with Docker Compose.
Persistent data storage is set up — no manual configuration needed.
Summary:
All containers are pre-configured and tested by the developer.
End users only need to download the project and run docker-compose up, and the system is fully functional.
GITHUB LINK / DOCKER HUB LINK OF THE MODIFIED CONTAINERS
GitHub Repository
Contains all the source files, Dockerfiles, and docker-compose.yml.
End Users: You only need to download the docker-compose.yml file to run the application. All containers are pre-built and available on Docker Hub, so no manual building is required.
Docker Hub Images
Backend: https://hub.docker.com/r/yuvaraj015/expense-tracker-backend
Frontend: https://hub.docker.com/r/yuvaraj015/expense-tracker-frontend
Database: https://hub.docker.com/_/postgres
PROJECT OUTCOMES
Full-Stack Application Development
Designed and implemented a complete Expense Tracker web application with a user-friendly interface.
Integrated essential features such as:
User authentication and session management
Transaction management (Add, Edit, Delete)
Real-time summary and category-wise expense analysis
Containerization Using Docker
Successfully Dockerized all components of the application - frontend, backend, and database - into isolated containers.
Ensured reproducibility and simplified deployment across systems.
Data Persistence and Reliability
Implemented persistent storage through PostgreSQL volumes to maintain user and transaction data across container restarts.
Ensured data integrity and consistent API performance during concurrent operations.
Multi-Container Orchestration
Configured and deployed a multi-container environment using Docker Compose, demonstrating practical container orchestration skills.
Verified seamless inter-container communication between Nginx (frontend), Node.js (backend), and PostgreSQL (database).
Image Management and Deployment
Built and published Docker images for frontend and backend services to Docker Hub, enabling easy access and redeployment.
Streamlined the deployment process by using prebuilt images instead of local builds.
Functional Validation and Testing
Conducted end-to-end testing of all major workflows: user registration, login, transaction CRUD operations, and summaries.
Validated frontend-backend integration, API responses, and database persistence.
CONCLUSION
The Expense Tracker web application demonstrates the complete development and deployment of a full-stack system using Docker and Docker Compose. Starting from a backend service with temporary data storage, the project progressed to a fully integrated multi-container system with a frontend interface and persistent PostgreSQL storage.
Containerizing the frontend, backend, and database services, and publishing images to Docker Hub, ensures portability, reproducibility, and ease of deployment on any Docker-enabled system. Comprehensive testing of user flows, API endpoints, and persistent data management validates both functionality and reliability. Overall, this project has provided practical experience in containerization, orchestration, full-stack development, and documentation, equipping the developer with skills for real-world deployment and collaborative environments.
REFERENCES
Original Sources of Docker Images
Docker Hub official images: PostgreSQL: https://hub.docker.com/_/postgres
Docker Tutorials
IIT Bombay Spoken Tutorial for Docker:
https://spoken-tutorial.org/tutorial-search/?search_foss=Docker&search_language=English
ACKNOWLEDGEMENTS
I would like to express my heartfelt gratitude to Dr. Subbulakshmi T, my course instructor for BCSE408L – Cloud Computing at the School of Computer Science and Engineering (SCOPE), Vellore Institute of Technology, Chennai, for her valuable guidance and continuous support throughout the completion of this project. Her insights into cloud technologies and containerization have been instrumental in helping me understand the practical aspects of Docker.
I would also like to acknowledge the learning resources provided by VIT Chennai and the IIT Bombay Spoken Tutorial, which were immensely helpful during the development process. Finally, I extend my appreciation to my friends who helped clarify doubts and provided constant encouragement during this project.




















































Comments
Post a Comment