diff --git a/src/problem4/.env b/src/problem4/.env new file mode 100644 index 0000000..e69de29 diff --git a/src/problem4/README.md b/src/problem4/README.md new file mode 100644 index 0000000..e82293d --- /dev/null +++ b/src/problem4/README.md @@ -0,0 +1,36 @@ +# Problem 4 + +A small platform has been deployed using Docker Compose. +Users are reporting that the API is unreliable and sometimes inaccessible. + +Your task is to investigate and stabilize the system. + +## Setup + +Requirements: + +* Docker +* Docker Compose + +Run: + +docker compose up --build + +The application will be available at: +[http://localhost:8080](http://localhost:8080) + +## Your Tasks + +1. Identify the issues affecting the system +2. Fix them +3. Explain the root causes + +## Submission + +Submit a short report including: + +* What problems you found +* How you diagnosed them +* The fixes you applied +* What monitoring/alerts you would add +* How you would prevent this in production diff --git a/src/problem4/api/Dockerfile b/src/problem4/api/Dockerfile new file mode 100644 index 0000000..6f65f06 --- /dev/null +++ b/src/problem4/api/Dockerfile @@ -0,0 +1,9 @@ +FROM node:20-alpine + +WORKDIR /app +COPY package.json . +RUN npm install + +COPY src ./src + +CMD ["node", "src/index.js"] \ No newline at end of file diff --git a/src/problem4/api/package.json b/src/problem4/api/package.json new file mode 100644 index 0000000..a954315 --- /dev/null +++ b/src/problem4/api/package.json @@ -0,0 +1,9 @@ +{ + "name": "api", + "version": "1.0.0", + "dependencies": { + "express": "^4.18.2", + "pg": "^8.11.3", + "ioredis": "^5.3.2" + } +} diff --git a/src/problem4/api/src/index.js b/src/problem4/api/src/index.js new file mode 100644 index 0000000..a6f466d --- /dev/null +++ b/src/problem4/api/src/index.js @@ -0,0 +1,35 @@ +const express = require("express"); +const { Pool } = require("pg"); +const Redis = require("ioredis"); + +const app = express(); + +const pool = new Pool({ + host: process.env.DB_HOST, + user: "postgres", + password: "postgres", + database: "postgres", + port: 5432, +}); + +const redis = new Redis({ host: process.env.REDIS_HOST, port: 6379 }); + +app.get("/api/users", async (req, res) => { + try { + const db = await pool.connect(); + const result = await db.query("SELECT NOW()"); + db.release(); + + await redis.set("last_call", Date.now()); + res.json({ ok: true, time: result.rows[0] }); + } catch (err) { + console.error(err); + res.status(500).json({ ok: false, error: err.message }); + } +}); + +app.get("/status", (req, res) => { + res.json({ status: "ok" }); +}); + +app.listen(3000, () => console.log("API running on 3000")); diff --git a/src/problem4/docker-compose.yml b/src/problem4/docker-compose.yml new file mode 100644 index 0000000..11bd063 --- /dev/null +++ b/src/problem4/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.9" + +services: + nginx: + image: nginx:1.25 + ports: + - "8080:80" + volumes: + - ./nginx/conf.d:/etc/nginx/conf.d + depends_on: + - api + + api: + build: ./api + environment: + - DB_HOST=postgres + - REDIS_HOST=redis + depends_on: + - postgres + - redis + + postgres: + image: postgres:15 + environment: + POSTGRES_PASSWORD: postgres + + redis: + image: redis:7 diff --git a/src/problem4/nginx/conf.d/default.conf b/src/problem4/nginx/conf.d/default.conf new file mode 100644 index 0000000..578be2f --- /dev/null +++ b/src/problem4/nginx/conf.d/default.conf @@ -0,0 +1,12 @@ +server { + listen 80; + + location = / { + return 200 "Welcome to the platform\n"; + } + + location /api/ { + proxy_pass http://api:3001; + } + +} diff --git a/src/problem4/nginx/nginx.conf b/src/problem4/nginx/nginx.conf new file mode 100644 index 0000000..e69de29 diff --git a/src/problem4/postgres/init.sql b/src/problem4/postgres/init.sql new file mode 100644 index 0000000..2b36506 --- /dev/null +++ b/src/problem4/postgres/init.sql @@ -0,0 +1 @@ +ALTER SYSTEM SET max_connections = 20;