Building a Fully Dockerized User Feedback Application with Flask and PostgreSQL
Source: Dev.to
Introduction
In this project, I built a full‑stack web application using Docker to demonstrate containerization concepts including Dockerfiles, Docker Compose, volumes, networking, and environment variables. The application allows users to submit feedback through a web interface, which is stored in a PostgreSQL database running in a Docker container.
Project Architecture
The system consists of three services:
- Frontend – static HTML/CSS/JS served via Nginx
- Backend – Flask REST API
- PostgreSQL Database
All services run in isolated containers connected through a custom Docker network.
Dockerfile Explanation
Backend Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.11-slim
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY . /app
WORKDIR /app
# Expose Flask port
EXPOSE 5000
# Run Flask app
CMD ["python", "app.py"]
Frontend Dockerfile (Nginx)
FROM nginx:alpine
# Copy static files into Nginx web directory
COPY ./static /usr/share/nginx/html
# Expose HTTP port
EXPOSE 80
Docker Compose Orchestration
Docker Compose orchestrates the multiple containers:
- PostgreSQL database
- Flask backend API
- Nginx frontend server
Service dependencies are defined using depends_on, and a custom Docker network enables inter‑container communication.
version: "3.9"
services:
db:
image: postgres:15
env_file: .env
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- feedback-net
backend:
build:
context: ./backend
dockerfile: Dockerfile
env_file: .env
depends_on:
- db
ports:
- "5000:5000"
networks:
- feedback-net
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
depends_on:
- backend
ports:
- "8080:80"
networks:
- feedback-net
networks:
feedback-net:
volumes:
pgdata:
Volumes and Networking
- Volume
pgdatapersists PostgreSQL data across container restarts. - Network
feedback-netallows containers to communicate using service names (e.g.,db,backend) instead of IP addresses.
Environment Variables
Sensitive data such as database credentials are stored in a .env file and injected into containers via Docker Compose. This avoids hard‑coding secrets in the source code.
POSTGRES_USER=feedback_user
POSTGRES_PASSWORD=secure_password
POSTGRES_DB=feedback_db
Challenges and Lessons Learned
- Networking: Understanding the difference between Docker’s internal networking (service names) and browser networking (localhost) was essential. Containers communicate via service names, while the host accesses exposed ports through
localhost. - Persistence: Ensuring database persistence required correctly configuring Docker volumes.
Conclusion
This project demonstrates real‑world Docker usage, including multi‑container orchestration, persistent storage, environment configuration, and networking. It highlights how Docker simplifies deploying full‑stack applications.
+--------------------+
| Browser |
+---------+----------+
|
v
+--------------------+
| Frontend (Nginx) |
| Container :8080 |
+---------+----------+
|
v
+--------------------+
| Backend (Flask) |
| Container :5000 |
+---------+----------+
|
v
+--------------------+
| PostgreSQL Database |
| Docker Volume pgdata|
+--------------------+