14 KiB
Task Manager — Dockerized Web Application
A modern task management web application deployed using Docker containers. The application consists of 5 services running in isolated containers, communicating over virtual networks, with persistent storage for data durability.
Table of Contents
- Description
- Prerequisites
- Architecture
- Services
- Networks
- Volumes
- Container Configuration
- Quick Start
- Usage Instructions
- Viewing the Application
- Example Workflow
- Sources
- AI Usage Declaration
Description
Task Manager is a full-stack web application for creating, managing, and tracking tasks. Users can:
- Create tasks with a title and optional description
- Mark tasks as completed or reopen them
- Delete tasks they no longer need
- Filter tasks by status (All / Active / Completed)
- View statistics including total, active, and completed task counts
- Manage the database via Adminer web interface
The application uses a modern dark-themed UI served by Nginx, a Node.js/Express REST API backend, PostgreSQL for persistent data storage, and Redis for response caching.
Prerequisites
To deploy and run this application, you need:
| Software | Minimum Version | Purpose |
|---|---|---|
| Linux | Any modern distribution | Host operating system |
| Docker | 20.10+ | Container runtime |
| Docker Compose | v2.0+ (plugin) | Multi-container orchestration |
| bash | 4.0+ | Running management scripts |
Verify installation:
docker --version # Docker version 20.10+
docker compose version # Docker Compose version v2.0+
bash --version # GNU bash, version 4.0+
Architecture
┌─────────────────────────────────────────────────────────┐
│ Docker Host │
│ │
│ ┌──────────────── frontend-net ──────────────────┐ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Nginx │ │ Adminer │ │ │
│ │ │ (frontend) │ │ (DB UI) │ │ │
│ │ │ :5000→:80 │ │ :5001→:5000│ │ │
│ │ └──────┬──────┘ └──────┬──────┘ │ │
│ │ │ │ │ │
│ └─────────┼────────────────────────┼──────────────┘ │
│ │ │ │
│ ┌─────────┼────────────────────────┼──────────────┐ │
│ │ │ backend-net │ │ │
│ │ ┌──────▼──────┐ │ │ │
│ │ │ Node.js │ │ │ │
│ │ │ (api) │ │ │ │
│ │ │ :3000 │ │ │ │
│ │ └──┬──────┬───┘ │ │ │
│ │ │ │ │ │ │
│ │ ┌──▼────┐ ┌▼─────────┐ ┌──────▼──────┐ │ │
│ │ │ Redis │ │PostgreSQL │ │ (Adminer │ │ │
│ │ │ :6379 │ │ :5432 │ │ connects) │ │ │
│ │ └───────┘ └───────────┘ └─────────────┘ │ │
│ │ 📦 📦 │ │
│ │ redisdata pgdata │ │
│ └─────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
Services
1. Frontend (Nginx)
- Container name:
taskapp-frontend - Image: Custom (built from
frontend/Dockerfileusingnginx:alpine) - Port:
5000(public) →80(container) - Role: Serves the static HTML/CSS/JS frontend and acts as a reverse proxy, forwarding
/api/requests to the Node.js backend - Networks:
frontend-net,backend-net
2. API (Node.js / Express)
- Container name:
taskapp-api - Image: Custom (built from
api/Dockerfileusingnode:20-alpine) - Port:
3000(virtual, not exposed to host) - Role: REST API server providing CRUD operations for tasks. Connects to PostgreSQL for data persistence and Redis for response caching
- Networks:
backend-net
3. PostgreSQL Database
- Container name:
taskapp-postgres - Image:
postgres:16-alpine - Port:
5432(virtual, not exposed to host) - Role: Primary relational database storing all task data
- Volume:
taskapp-pgdatamounted at/var/lib/postgresql/data - Networks:
backend-net - Initialization:
db/init.sqlis automatically executed on first run to create thetaskstable
4. Redis Cache
- Container name:
taskapp-redis - Image:
redis:7-alpine - Port:
6379(virtual, not exposed to host) - Role: In-memory cache for API responses. Reduces database load by caching task list queries for 30 seconds. Configured with append-only persistence
- Volume:
taskapp-redisdatamounted at/data - Networks:
backend-net
5. Adminer (Database Web Interface)
- Container name:
taskapp-adminer - Image:
adminer:latest - Port:
5001(public) →5000(container) - Role: Web-based database management tool. Allows direct SQL queries, table browsing, and data export
- Networks:
frontend-net,backend-net
Networks
| Network Name | Driver | Connected Services | Purpose |
|---|---|---|---|
taskapp-frontend-net |
bridge | frontend, adminer | Isolates user-facing services |
taskapp-backend-net |
bridge | frontend, api, postgres, redis, adminer | Connects backend services for internal communication |
Why two networks?
- Services on
frontend-netare publicly accessible - Services on
backend-nethandle internal communication - The
frontendandadminerservices bridge both networks since they need public access while communicating with backend services
Volumes
| Volume Name | Mount Point | Service | Purpose |
|---|---|---|---|
taskapp-pgdata |
/var/lib/postgresql/data |
postgres | Persists database files across container restarts |
taskapp-redisdata |
/data |
redis | Persists Redis append-only file for cache durability |
Data persistence: Stopping and restarting the application (./stop-app.sh then ./start-app.sh) preserves all data. Only ./remove-app.sh deletes the volumes.
Container Configuration
All containers are configured with:
- Restart policy:
unless-stopped— containers automatically restart on failure or system reboot - Health checks: PostgreSQL and Redis have health checks; the API and frontend wait for healthy dependencies before starting
- Dependencies:
docker composeensures services start in the correct order:- PostgreSQL + Redis (database layer)
- API (depends on healthy postgres and redis)
- Frontend + Adminer (depends on api and postgres respectively)
- Environment variables: Database credentials and connection parameters are passed via environment variables in
docker-compose.yaml
Quick Start
# 1. Prepare the application (build images, create networks/volumes)
./prepare-app.sh
# 2. Start the application
./start-app.sh
# 3. Open in browser
# Task Manager: http://localhost:5000
# Adminer: http://localhost:5001
Usage Instructions
Preparing the application
./prepare-app.sh
This script builds the custom Docker images (frontend, api), and creates the required networks and volumes.
Starting the application
./start-app.sh
Starts all 5 containers in detached mode. Prints the URLs for accessing the application.
Stopping the application
./stop-app.sh
Stops all containers without removing data. Your tasks and database state are preserved in the persistent volumes.
Restarting after stop
./start-app.sh
Simply run the start script again. All your data will be intact.
Removing the application
./remove-app.sh
⚠️ Warning: This removes ALL traces of the application including:
- All containers
- All networks
- All persistent volumes (data is lost)
- All locally built images
Viewing the Application
Task Manager (Main Application)
- URL: http://localhost:5000
- Features: Create, complete, delete, and filter tasks
Adminer (Database Management)
- URL: http://localhost:5001
- Login credentials:
- System: PostgreSQL
- Server:
postgres - Username:
taskuser - Password:
taskpass - Database:
taskmanager
Example Workflow
# Prepare the application
$ ./prepare-app.sh
=============================================
Preparing Task Manager Application...
=============================================
[1/3] Building Docker images...
✓ Images built successfully
[2/3] Creating networks...
✓ Networks created
[3/3] Creating volumes...
✓ Volumes created
=============================================
✓ Application prepared successfully!
Run ./start-app.sh to start the application
=============================================
# Start the application
$ ./start-app.sh
=============================================
Starting Task Manager Application...
=============================================
[1/2] Starting containers...
[2/2] Waiting for services to be ready...
=============================================
✓ Application is running!
🌐 Task Manager: http://localhost:5000
🗄️ Adminer (DB): http://localhost:5001
=============================================
# Open http://localhost:5000 in a web browser and work with the application
# Create tasks, mark them complete, delete them, etc.
# Stop the application (data is preserved)
$ ./stop-app.sh
=============================================
Stopping Task Manager Application...
=============================================
✓ Application stopped.
Data is preserved in persistent volumes.
Run ./start-app.sh to restart.
# Start again - all tasks are still there!
$ ./start-app.sh
# When done, remove everything
$ ./remove-app.sh
=============================================
Removing Task Manager Application...
=============================================
✓ Application completely removed.
Sources
- Docker Documentation — https://docs.docker.com/
- Docker Compose Documentation — https://docs.docker.com/compose/
- Nginx Docker Image — https://hub.docker.com/_/nginx
- Node.js Docker Image — https://hub.docker.com/_/node
- PostgreSQL Docker Image — https://hub.docker.com/_/postgres
- Redis Docker Image — https://hub.docker.com/_/redis
- Adminer Docker Image — https://hub.docker.com/_/adminer
- Express.js Documentation — https://expressjs.com/
- node-postgres (pg) Documentation — https://node-postgres.com/
- Node Redis Client — https://github.com/redis/node-redis
Use of Artificial Intelligence
Artificial intelligence tools such as ChatGPT and Claude were used as a support tool during development for understanding Docker concepts and debugging scripts. Some configuration issues were also fixed by referring to AI. All implementation, testing, and integration were performed independently.
Project Structure
z1/
├── docker-compose.yaml # Main orchestration configuration
├── prepare-app.sh # Build images, create networks/volumes
├── start-app.sh # Start all services
├── stop-app.sh # Stop without data loss
├── remove-app.sh # Remove all traces
├── README.md # This documentation
├── frontend/ # Nginx + Static frontend
│ ├── Dockerfile # Nginx container build
│ ├── nginx.conf # Nginx configuration
│ └── public/
│ ├── index.html # Task Manager HTML
│ ├── style.css # Styles (dark theme)
│ └── app.js # Frontend JavaScript
├── api/ # Node.js REST API
│ ├── Dockerfile # API container build
│ ├── package.json # Node.js dependencies
│ ├── server.js # Express API server
│ └── db.js # PostgreSQL connection
└── db/
└── init.sql # Database initialization