Containerizing and Orchestrating of TaskZen
Containerizing and Orchestrating a Full-Stack Task Management Application (TaskZen) with Docker and Docker Compose.
Introduction
This document provides a detailed, step-by-step
account of containerizing a modern, full-stack web application, "TaskZen."
The application consists of a Python-based FastAPI backend and a React.js
frontend. The primary goal of this exercise is to encapsulate each service into
a portable, isolated Docker container, orchestrate their deployment using Docker
Compose, and finally, publish the resulting images to a public container
registry (Docker Hub). This process demonstrates a fundamental DevOps workflow for
ensuring consistency, scalability, and ease of deployment across different
environments.
Objectives of Part 1:
The primary objective of Part 1 is to achieve standalone containerization for the frontend and backend services. This involves:
- Creating
a dedicated Dockerfile for the Python FastAPI backend to define its
environment, dependencies, and execution command.
- Creating
a multi-stage Dockerfile for the React frontend to build the static assets
and serve them efficiently using an Nginx web server.
- Building
Docker images for each service locally and verifying their integrity.
- Running
each container independently to confirm that the services operate
correctly in isolation.
Objectives of Part 2:
The objective of Part 2 is to orchestrate the separately containerized services into a cohesive, single-command deployment. This is achieved by:
- Creating
a docker-compose.yml file to define the multi-container application stack,
including the backend and frontend services.
- Establishing
network communication between the frontend and backend containers.
- Managing
service dependencies to ensure the backend starts before the frontend
attempts to connect.
- Launching
the entire application stack using a single docker-compose up command and
verifying inter-container connectivity.
Objectives of Part 3
The final objective is to make the containerized application distributable and publicly accessible for deployment on any machine with Docker. This involves:
- Authenticating
with Docker Hub via the Docker CLI.
- Correctly
tagging the locally built frontend and backend images with the Docker Hub
repository namespace.
- Pushing
the tagged images to the public Docker Hub registry.
- Verifying
the successful upload by checking the Docker Hub web interface and pulling
the images on a different system.
Names of the containers involved and download links
This project is built from original source code and does not use pre-existing containers from external sources. The base images used in the Dockerfile configurations are official, open-source images:
- python:3.11-slim:
The official lightweight Python image used for the backend service.
- Download
Link: https://hub.docker.com/_/python
- node:22-alpine:
The official lightweight Node.js image used for the build stage of the
frontend service.
- Download
Link: https://hub.docker.com/_/node
- nginx:alpine:
The official lightweight Nginx image used to serve the static frontend
assets.
- Download
Link: https://hub.docker.com/_/nginx
Other software involved and purpose
Development and Orchestration Tools
|
Tool |
Purpose |
Version |
|
Node.js |
JavaScript runtime environment for frontend development
and build processes. |
22+ |
|
Python |
Programming language for building the high-performance
backend API. |
3.11+ |
|
Docker Desktop |
Core container platform for building, running, and
managing isolated application environments. |
N/A |
|
Docker Compose |
Multi-container orchestration tool for defining and
running the full application stack (frontend + backend) with a single
command. |
3.9 |
|
Visual Studio Code |
Integrated Development Environment (IDE) for code
development and project management. |
N/A |
Frontend Technologies (React)
The frontend is a Single-Page Application (SPA) focused
on performance and modern UI design.
|
Technology |
Role |
Version |
|
React |
Primary JavaScript library for building interactive
user interfaces. |
19.1.1 |
|
Vite |
Next-generation frontend build tool and development
server for rapid development. |
7.1.2 |
|
Tailwind CSS |
Utility-first CSS framework enabling rapid, highly
customizable UI development. |
4.1.12 |
|
React Router DOM |
Declarative routing library essential for navigation in
the React SPA. |
7.8.2 |
|
Nginx Alpine |
Lightweight production-grade web server used within the
Docker container to serve static frontend assets. |
N/A |
|
Lucide React |
Icon library providing beautiful and consistent SVG
icons for the UI. |
0.542.0 |
Backend Technologies (FastAPI/Python)
The backend is built as a fast, asynchronous REST API
using Python's modern ecosystem.
|
Technology |
Role |
Version |
|
FastAPI |
Modern, high-performance Python web framework for
building the REST APIs. |
0.116.1+ |
|
Uvicorn |
Lightning-fast ASGI server responsible for running the
FastAPI application efficiently. |
0.35.0+ |
|
SQLAlchemy |
Python SQL toolkit and ORM for robust and efficient
database interactions. |
2.0.43+ |
|
Pydantic |
Data validation library used by FastAPI to define data
schemas and enforce type safety. |
N/A |
|
iCalendar |
Library for parsing and generating iCalendar files
(e.g., for task scheduling/export). |
6.0.0+ |
|
python-dateutil |
Provides powerful extensions to the standard Python datetime
module for date handling. |
2.8.2+ |
Database and Authentication
|
System/Tool |
Purpose |
Version |
|
Supabase |
Open-source platform acting as the primary
backend-as-a-service, handling data and authentication. |
2.18.1+ |
|
PostgreSQL |
The core robust relational database system provided by
Supabase. |
N/A |
|
Supabase Auth |
Built-in system for user management, session handling,
and secure authentication. |
N/A |
Supporting Tools
|
Tool |
Role |
Version |
|
python-dotenv |
Manages environment variables for secure configuration
and credentials. |
1.1.1+ |
|
ESLint |
JavaScript linting tool ensuring code quality, style
consistency, and catching errors early. |
9.33.0 |
|
PostCSS |
Tool used for transforming CSS with JavaScript plugins,
often integrated with Tailwind CSS. |
8.5.6 |
Overall architecture diagrams and explanations
Text Description of the Flow:
The overall architecture follows a standard client-server model, externalized through Docker containers.
- Part 1 (Containerization): The backend source code is the input to its Dockerfile, producing a taskzen-backend Docker image. Similarly, the frontend source code is the input to its Dockerfile, producing a taskzen-frontend image. The output is two independent, runnable Docker images stored locally.
- Part
2 (Orchestration): The docker-compose.yml file takes the two build
contexts (frontend and backend directories) as input. The docker-compose
up command triggers the image builds and then starts two containers. The frontend
container, upon receiving a user request from a web browser, makes an API
call to the backend container over the Docker-managed network. The output
is a fully functional, networked application running locally.
- Part 3 (Distribution): The locally built taskzen-frontend and taskzen-backend images are the input. The docker push command sends these images to Docker Hub. The output is the public availability of these images in a remote repository for anyone to pull and run.
Full DA Input/Output Flow:
A user interacts with their web browser, which sends an
HTTP request to the Nginx server in the taskzen-frontend container. Nginx
serves the React application. The React app then makes API calls to the FastAPI
server in the taskzen-backend container. The backend processes these requests,
queries the external Supabase PostgreSQL database, and returns a response to
the frontend, which then updates the UI for the user.
Logical Issues Found:
The provided architecture is logically sound for a modern
web application. The separation of concerns between the frontend, backend, and
database is clear. The use of Nginx to serve the static React build is a
production-ready practice. The only potential point of failure is the network
dependency on the external Supabase database; if the containers cannot reach
the internet, the application will fail. This is an acceptable design choice
for this architecture.
Architecture Diagram:
Architecture Explanation:
The system employs a decoupled, service-oriented
architecture implemented with Docker containers. The user-facing component is a
taskzen-frontend container, which runs a lightweight Nginx server. This
server's sole responsibility is to efficiently deliver the pre-built static
files of the React.js single-page application (SPA) to the user's browser. This
containerization ensures that the frontend's environment and dependencies are
isolated and consistent. All business logic, data processing, and
database interactions are handled by the taskzen-backend container. This
container runs a FastAPI application, exposing a RESTful API that the frontend
consumes. By separating the backend, we can scale, update, and maintain it
independently of the user interface. This backend container communicates with
an external, cloud-hosted Supabase instance, which provides the PostgreSQL
database for data persistence and handles user authentication, ensuring data is
securely managed outside the containerized environment.
Procedure — Part 1 (Dockerizing Frontend and Backend Separately)
In this part, we create Docker images for the frontend and backend applications individually.
Step 1: Create Backend Dockerfile
A Dockerfile is created in the backend directory to
define the steps for building the Python application image.
Step 2: Build the Backend Docker Image
Navigate to the project's root directory and run the build command.
Bash:docker build -t taskzen-backend .
Step 3: Run the Backend Container
Run the newly created image as a container to verify it works.
Bash: docker run -p 8000:8000 taskzen-backend
Step 4: Create Frontend Dockerfile
A multi-stage Dockerfile is created in the frontend
directory. The first stage builds the React app, and the second stage serves
the build artifacts with Nginx.
Step 5: Build the Frontend Docker Image
From the root directory, build the frontend image.
Bash: docker build -t taskzen-frontend .
Step 6: Run the Frontend Container
Run the frontend container and map the port to access it
from the browser.
Bash: docker run -p 5173:80 taskzen-frontend
Step 7 – Running Containers
Step 8 – Frontend
Step 9 – Backend
Procedure — Part 2 (Orchestrating with Docker Compose)
Here, we use Docker Compose to manage and run the multi-container application.
Step 1: Create docker-compose.yml File
Create a docker-compose.yml file in the project root to
define both services.
Step 2: Launch the Application Stack
Run a single command from the root directory to build and start both containers.
Bash: docker-compose up --build -d
Step 3: Verify Running Containers
Check the status of the running containers to ensure both
are up and healthy.
Bash: docker-compose ps
Step 4: Basic Troubleshooting
To view logs for a specific service (e.g., the backend):
Bash:docker-compose logs backend
To stop and remove the containers:
Bash: docker-compose down
Procedure — Part 3 (Uploading to Docker Hub)
This part covers publishing the custom images to a public registry.
Step 1: Log in to Docker Hub
Use the Docker CLI to authenticate with your Docker Hub
account.
Bash: docker login
Step 2: Tag the Local Images
Tag your local images with your Docker Hub username and repository name. Replace your-dockerhub-username with your actual username.
Bash:
docker tag taskzen-backend your-dockerhub-username /taskzen-backend:latest
docker tag taskzen-frontend your-dockerhub-username /taskzen-frontend:lates
Step 3: Push the Images to Docker Hub
Push the tagged images to the remote repository.
Bash:
docker push your-dockerhub-username/taskzen-backend:latest
docker push
your-dockerhub-username/taskzen-frontend:latest
Step 4: Verify on Docker Hub
Navigate to your Docker Hub profile in a web browser to confirm that both repositories (taskzen-backend and taskzen-frontend) have been created and contain the latest tag.
Modifications done to containers after downloading
This project was developed from scratch, so no existing
containers were downloaded and modified. The Dockerfiles were created to
containerize original source code. The primary modifications involved:
- Base
Image Selection: Choosing lightweight and official base images (python:3.11-slim,
node:22-alpine, nginx:alpine) to keep the final image sizes small and
secure.
- Multi-Stage
Build (Frontend): Implementing a multi-stage build in the frontend Dockerfile
was a key modification. This separates the build environment (with Node.js
and npm) from the production environment (with Nginx), resulting in a much
smaller and more secure final image that only contains the necessary
static files and the web server.
- Nginx
Configuration: A custom nginx.conf was added to the frontend container.
This configuration is crucial for a Single-Page Application (SPA) as it
redirects all routing requests to index.html, allowing the client-side
React Router to handle them.
GitHub link / Docker Hub link of modified containers
- GitHub
Repository: https://github.com/RadieNoice/TaskZen
- Docker
Hub Repositories:
Outcomes of your DA
- Successfully
created reproducible, isolated environments for both the frontend and
backend services using Dockerfiles.
- Demonstrated
the ability to build and run each service as a standalone Docker
container.
- Orchestrated
a multi-container application using Docker Compose, establishing a network
bridge for inter-service communication.
- Implemented
a production-ready pattern for serving a React application using a
multi-stage build with Nginx.
- Successfully
published the custom application images to Docker Hub, making them
portable and easily distributable for deployment on any Docker-enabled
host.
- Gained
practical experience in a core DevOps workflow, from source code to a
distributable containerized application.
Conclusion
This project successfully demonstrated the
end-to-end process of containerizing and orchestrating a full-stack
application. By leveraging Docker, we transformed a complex development setup
into a simple, portable, and reproducible set of images. Docker Compose further
simplified the process, allowing the entire application stack to be managed
with a single command. The final step of publishing to Docker Hub completes the
workflow, enabling seamless distribution and deployment. This exercise underscores
the power of containerization in modern software development, providing a
robust foundation for building scalable and maintainable systems.
References
Official Docker Documentation: https://docs.docker.com/
Docker Hub: https://hub.docker.com/
IIT Bombay Spoken Tutorial (Docker): https://spoken-tutorial.org/tutorial-search/?search_foss=Docker&search_language=English
FastAPI Documentation: https://fastapi.tiangolo.com/
VIT SCOPE Course Materials: Cloud Computing (Current Semester)
Acknowledgements
I would like to express my sincere gratitude to Dr. T. Subbulakshmi for providing clear instructions and guidance throughout the completion of this Digital Assignment.
Special thanks to VIT SCOPE, under which this Cloud Computing course was offered, for enabling a practical understanding of containerization concepts through this project.
I also acknowledge the help of the official Docker and FastAPI documentation, which were invaluable resources during the development process.
Finally, I extend heartfelt thanks to my family, friends, and course instructor for their consistent support, motivation, and feedback throughout the project.
— Written by Dhilip Kumar P
Comments
Post a Comment