3-service Docker app: Nginx frontend, Flask REST API backend, PostgreSQL database. Includes lifecycle scripts (prepare, start, stop, remove), docker-compose.yaml, and documentation.
6.8 KiB
Task Manager - Docker Web Application
A simple task manager web application deployed as a multi-container Docker system. Users can create, complete, and delete tasks through a web interface.
Prerequisites
- Linux with Docker installed (Docker Engine 20.10+)
- Docker Compose v2 (optional, for
docker composedeployment) - Ports 80 must be available on the host machine
Application Description
The Task Manager is a web-based CRUD application for managing personal tasks. It consists of three services working together:
- A frontend web interface served by Nginx where users interact with the application
- A backend REST API built with Flask (Python) that handles business logic
- A PostgreSQL database that stores task data persistently
Users can:
- Add new tasks
- Mark tasks as completed (toggle checkbox)
- Delete tasks
- View all tasks in a list sorted by creation date
Architecture
Browser (port 80)
|
v
+--------+ +-------+ +------------+
| Nginx | ----> | Flask | ----> | PostgreSQL |
| :80 | API | :5000 | SQL | :5432 |
+--------+ proxy +-------+ +------------+
static REST API persistent
files (gunicorn) volume
Virtual Networks
| Network Name | Driver | Purpose |
|---|---|---|
| taskapp-network | bridge | Connects all 3 containers so they can communicate |
All containers are attached to taskapp-network. Only Nginx exposes a port (80) to the host. Flask and PostgreSQL are accessible only within the Docker network.
Named Volumes
| Volume Name | Mount Point | Purpose |
|---|---|---|
| taskapp-pgdata | /var/lib/postgresql/data (in db) | Persists database data across container restarts and stops |
Stopping and restarting the application preserves all task data thanks to this volume.
Containers
1. taskapp-nginx (Frontend)
- Image: Custom, built from
nginx:alpine - Port: 80 (host) -> 80 (container)
- Role: Serves static HTML/CSS/JS files and reverse-proxies
/api/*requests to the Flask backend - Restart policy:
unless-stopped - Configuration: Custom
nginx.confwithproxy_passdirective for API routing
2. taskapp-flask (Backend)
- Image: Custom, built from
python:3.12-slim - Port: 5000 (internal only, not exposed to host)
- Role: REST API server handling task CRUD operations
- Restart policy:
unless-stopped - Configuration: Environment variables for database connection (
DB_HOST,DB_NAME,DB_USER,DB_PASSWORD) - WSGI server: Gunicorn with 2 workers
- Auto-initialization: Creates the
taskstable on startup if it does not exist
3. taskapp-db (Database)
- Image:
postgres:15(from Docker Hub) - Port: 5432 (internal only, not exposed to host)
- Role: Stores task data (id, title, completed status, creation timestamp)
- Restart policy:
unless-stopped - Configuration: Environment variables (
POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD) - Volume:
taskapp-pgdatamounted at/var/lib/postgresql/data
Container Configuration Details
- Nginx is configured via
frontend/nginx.confwhich sets up static file serving and reverse proxy rules - Flask reads database credentials from environment variables passed at container runtime
- PostgreSQL is configured via standard Postgres environment variables; data is stored on a named volume
Usage Instructions
Prepare the Application
Build images and create Docker resources:
./prepare-app.sh
Start the Application
Run all containers:
./start-app.sh
Output:
Starting app...
App is running!
The app is available at http://localhost:80
View in Web Browser
Open your web browser and navigate to:
http://localhost:80
You will see the Task Manager interface where you can add, complete, and delete tasks.
Stop the Application
Stop all containers (data is preserved):
./stop-app.sh
Remove the Application
Remove all containers, images, networks, and volumes:
./remove-app.sh
Alternative: Docker Compose
You can also use Docker Compose instead of the shell scripts:
# Start
docker compose up -d --build
# Stop (preserves data)
docker compose down
# Remove everything including volumes
docker compose down -v --rmi all
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/tasks | List all tasks |
| POST | /api/tasks | Create a new task |
| PUT | /api/tasks/:id | Toggle task completion |
| DELETE | /api/tasks/:id | Delete a task |
Project Structure
.
├── backend/
│ ├── Dockerfile # Python/Flask image definition
│ ├── requirements.txt # Python dependencies
│ └── app.py # Flask REST API application
├── frontend/
│ ├── Dockerfile # Nginx image definition
│ ├── nginx.conf # Nginx configuration (static files + reverse proxy)
│ ├── index.html # Main HTML page
│ ├── style.css # Styles
│ └── app.js # Frontend JavaScript (fetch API calls)
├── docker-compose.yaml # Docker Compose configuration
├── prepare-app.sh # Script to build images and create resources
├── start-app.sh # Script to start all containers
├── stop-app.sh # Script to stop all containers
├── remove-app.sh # Script to remove all traces of the app
└── README.md # This file
Sources
- Docker Documentation
- Nginx Docker Image
- PostgreSQL Docker Image
- Python Docker Image
- Flask Documentation
- Gunicorn Documentation
- Nginx Reverse Proxy Guide
Use of Artificial Intelligence
This application was designed and implemented with the assistance of Claude (Anthropic), an AI assistant. Claude was used for:
- Designing the application architecture and service composition
- Writing application source code (Python/Flask backend, HTML/CSS/JS frontend)
- Writing Dockerfiles and Docker Compose configuration
- Writing shell scripts for application lifecycle management
- Writing this documentation
AI agent used: Claude Opus 4.6 (Anthropic) via Claude Code CLI