# Notes App — Docker Assignment ## What the application does A simple **Notes** web application where users can create, view, and delete short text notes. Notes are stored persistently in a PostgreSQL database. The app is accessible via a web browser. ## Services | Container | Image | Port | Description | |---|---|---|---| | `app_frontend` | custom (Nginx) | `8080→80` | Serves the static HTML/JS frontend and proxies `/api/` requests to the backend | | `app_backend` | custom (Flask/Python) | internal `5000` | REST API for CRUD operations on notes | | `app_db` | `postgres:16-alpine` | internal `5432` | Relational database storing notes persistently | | `app_adminer` | `adminer:4` | `8081→8080` | Web UI for browsing and managing the PostgreSQL database | ## Networks | Network | Purpose | |---|---| | `frontend_net` | Connects the Nginx frontend container (externally reachable) | | `backend_net` | Internal network connecting frontend→backend→database and Adminer→database | The database is only on `backend_net` and is never directly exposed to the host. ## Volumes | Volume | Used by | Purpose | |---|---|---| | `postgres_data` | `app_db` | Persists PostgreSQL data across container restarts and stops | ## Container configuration - **app_db**: configured via environment variables (`POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`). The `db/init.sql` file is mounted read-only into `/docker-entrypoint-initdb.d/` and runs once on first startup to create the `notes` table and insert seed data. - **app_backend**: receives `DATABASE_URL` as an environment variable pointing to the `db` service. Built from `./backend/Dockerfile` using Python 3.12-slim with Flask and psycopg2. - **app_frontend**: built from `./frontend/Dockerfile` using Nginx 1.27-alpine. The custom `nginx.conf` proxies all `/api/` requests to `app_backend:5000` and serves `index.html` for all other paths. - **app_adminer**: uses the official Adminer image with no extra configuration. Reachable on port `8081`. - All containers use `restart: on-failure`. ## Requirements - Linux OS - Docker Engine ≥ 24 with the Compose plugin (`docker compose`) ## Instructions ### Prepare (build images) ```bash ./prepare-app.sh ``` ### Start ```bash ./start-app.sh ``` ### Stop (data is preserved) ```bash ./stop-app.sh ``` ### Remove everything ```bash ./remove-app.sh ``` ## Viewing the application | URL | Description | |---|---| | http://localhost:8080 | Notes web application | | http://localhost:8081 | Adminer — log in with Server: `db`, User: `appuser`, Password: `apppassword`, Database: `appdb` | ## Example workflow ```bash ./prepare-app.sh # Preparing app... ./start-app.sh # Running app... # The app is available at http://localhost:8080 # Adminer (DB UI) is available at http://localhost:8081 # Open browser, add/delete notes ./stop-app.sh # Stopping app... # App stopped. Data in volumes is preserved. ./start-app.sh # Notes are still there — volume was preserved ./remove-app.sh # Removing app. ``` ## Resources used - [Docker documentation](https://docs.docker.com/) - [Flask documentation](https://flask.palletsprojects.com/) - [Nginx documentation](https://nginx.org/en/docs/) - [PostgreSQL Docker image](https://hub.docker.com/_/postgres) - [Adminer Docker image](https://hub.docker.com/_/adminer) ## Use of artificial intelligence This project was created with the assistance of **Kiro AI** (kiro-cli chat agent). The AI generated the initial structure of all files including the Docker Compose configuration, Flask application, Nginx configuration, frontend HTML/JS, and shell scripts. All generated code was reviewed and understood by the author. The AI was used as a coding assistant, not as a replacement for understanding the solution.