commit 99bc49225b56fc9a54ce0da17c2cae0456333723 Author: root Date: Wed Apr 1 00:38:48 2026 +0200 Final Docker multi-service application diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ef2380 --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +# Docker Multi-Service Notes Application + +## Project Overview + +This project is a multi-container web application deployed using Docker. It demonstrates how different services can work together using containerization. + +The application allows users to: + +- Add and delete notes +- Upload files +- View and download uploaded files + +--- + +## Architecture + +The application consists of the following services: + +**Frontend (Nginx)** +Serves static HTML, CSS, and JavaScript files. Accessible via browser. + +**Backend (Node.js + Express)** +Handles API requests and manages notes and file uploads. + +**MongoDB** +Stores notes data and uses a persistent Docker volume. + +**Mongo Express** +Provides a web interface to view and manage database data. + +--- + +## Technologies Used + +- Docker and Docker Compose +- Node.js with Express +- MongoDB (NoSQL database) +- Nginx (web server) +- HTML, CSS, and JavaScript + +--- + +## Service Ports + +| Service | Port | +|---------------|------| +| Frontend | 8080 | +| Backend | 3000 | +| Mongo Express | 8081 | + +--- + +## Persistent Storage + +The application uses Docker volumes to preserve data across container restarts: + +- `mongo-data` stores database records +- `uploads/` stores user-uploaded files + +Data is retained even after stopping the application. + +--- + +## How to Run + +### 1. Prepare the application + +```bash +./prepare-app.sh +``` + +### 2. Start the application + +```bash +./start-app.sh +``` + +Once running, open the following in your browser: + +- Application: `http://147.232.204.210:8080` +- Database UI: `http://147.232.204.210/:8081` + +### 3. Stop the application + +```bash +./stop-app.sh +``` + +### 4. Remove the application + +```bash +./remove-app.sh +``` + +--- + +## Application Workflow + +1. The user interacts with the frontend in a browser. +2. The frontend sends API requests to the backend. +3. The backend processes the requests and communicates with MongoDB. +4. MongoDB stores or retrieves the relevant data. +5. Mongo Express provides a separate interface to inspect database content directly. + +--- + +## Features + +- Create and delete notes +- Upload files +- View and download uploaded files +- Persistent storage via Docker volumes diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..b2fb062 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,6 @@ +FROM node:18 +WORKDIR /app +COPY package.json . +RUN npm install +COPY . . +CMD ["node", "app.js"] diff --git a/backend/Dockerfile.save b/backend/Dockerfile.save new file mode 100644 index 0000000..9c2f352 --- /dev/null +++ b/backend/Dockerfile.save @@ -0,0 +1,58 @@ + GNU nano 7.2 backend/Dockerfile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [ New File ] +^G Help ^O Write Out ^W Where Is ^K Cut ^T Execute ^C Location M-U Undo M-A Set Mark M-] To Bracket M-Q Previous ^B Back ^◂ Prev Word +^X Exit ^R Read File ^\ Replace ^U Paste ^J Justify ^/ Go To Line M-E Redo M-6 Copy ^Q Where Was M-W Next ^F Forward ^▸ Next Word diff --git a/backend/app.js b/backend/app.js new file mode 100644 index 0000000..0d9ff23 --- /dev/null +++ b/backend/app.js @@ -0,0 +1,57 @@ + + +const express = require("express"); +const mongoose = require("mongoose"); +const multer = require("multer"); +const cors = require("cors"); +const fs = require("fs"); + +const app = express(); +app.use(express.json()); +app.use(cors()); + +app.use("/uploads", express.static("uploads")); +mongoose.connect("mongodb://mongo:27017/notes"); + +const Note = mongoose.model("Note", { text: String }); + +const storage = multer.diskStorage({ + destination: "uploads/", + filename: (req, file, cb) => { + cb(null, Date.now() + "-" + file.originalname); + } +}); + +const upload = multer({ storage }); + +app.get("/notes", async (req, res) => { + res.json(await Note.find()); +}); + +app.post("/notes", async (req, res) => { + const note = new Note(req.body); + await note.save(); + res.json(note); +}); + +app.post("/upload", upload.single("file"), (req, res) => { + res.json({ message: "Uploaded" }); +}); + +app.listen(3000, () => console.log("Backend running")); + +app.get("/", (req, res) => { + res.send("Backend is running"); +}); + +app.delete("/notes/:id", async (req, res) => { + await Note.findByIdAndDelete(req.params.id); + res.json({ message: "Deleted" }); +}); + +app.get("/files", (req, res) => { + fs.readdir("uploads/", (err, files) => { + if (err) return res.status(500).send("Error"); + res.json(files); + }); +}); diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..158855b --- /dev/null +++ b/backend/package.json @@ -0,0 +1,10 @@ +{ + "name": "notes-app", + "version": "1.0.0", + "dependencies": { + "express": "^4.18.2", + "mongoose": "^7.0.0", + "multer": "^1.4.5-lts.1", + "cors": "^2.8.5" + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..320f711 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: "3.8" + +services: + frontend: + image: nginx + ports: + - "8080:80" + volumes: + - ./frontend:/usr/share/nginx/html + + backend: + build: ./backend + ports: + - "3000:3000" + volumes: + - ./uploads:/app/uploads + depends_on: + - mongo + restart: always + + mongo: + image: mongo + volumes: + - mongo-data:/data/db + restart: always + + mongo-express: + image: mongo-express + ports: + - "8081:8081" + depends_on: + - mongo + environment: + ME_CONFIG_MONGODB_SERVER: mongo + restart: always + +volumes: + mongo-data: diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..1161738 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,214 @@ + + + + + Notes Application + + + + + + +
+

Notes Application

+ +
+ + +
+ + + +
+

Upload File

+ + +
+ +

Files

+ + +
+ + + + + diff --git a/prepare-app.sh b/prepare-app.sh new file mode 100755 index 0000000..8d52be0 --- /dev/null +++ b/prepare-app.sh @@ -0,0 +1,5 @@ +#!/bin/bash +docker network create app-network 2>/dev/null +docker volume create mongo-data +docker volume create uploads +docker-compose build diff --git a/remove-app.sh b/remove-app.sh new file mode 100755 index 0000000..1261387 --- /dev/null +++ b/remove-app.sh @@ -0,0 +1,4 @@ +#!/bin/bash +docker-compose down -v +docker system prune -f + diff --git a/start-app.sh b/start-app.sh new file mode 100755 index 0000000..ae3c3c6 --- /dev/null +++ b/start-app.sh @@ -0,0 +1,5 @@ +#!/bin/bash +docker-compose up -d + +echo "App running at: http://147.232.204.210:8080" +echo "Mongo Express: http://147.232.204.210:8081" diff --git a/stop-app.sh b/stop-app.sh new file mode 100755 index 0000000..489373b --- /dev/null +++ b/stop-app.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down diff --git a/uploads/1774538855945-ast_tree (28).png b/uploads/1774538855945-ast_tree (28).png new file mode 100644 index 0000000..394cdb1 Binary files /dev/null and b/uploads/1774538855945-ast_tree (28).png differ diff --git a/uploads/1774540108005-ast_tree (30).png b/uploads/1774540108005-ast_tree (30).png new file mode 100644 index 0000000..bb15ca1 Binary files /dev/null and b/uploads/1774540108005-ast_tree (30).png differ diff --git a/uploads/1774542769899-tseitin_tree (8).jpeg b/uploads/1774542769899-tseitin_tree (8).jpeg new file mode 100644 index 0000000..1cdfc3c Binary files /dev/null and b/uploads/1774542769899-tseitin_tree (8).jpeg differ