Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mysql-db
13 changes: 4 additions & 9 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
# Use the official Node.js 20 image as the base image
FROM node:20
FROM node

# Set the working directory in the container
WORKDIR /app

# Copy the package.json and package-lock.json files to the container
COPY package*.json ./

# Install the dependencies
RUN npm install

# Copy the rest of the application's source code to the container
COPY . .

# Expose the port that the application listens on
EXPOSE 3000

# Start the Node.js application
CMD [ "npm", "start" ]
CMD ["npm", "start"]


108 changes: 50 additions & 58 deletions backend/server.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,91 @@
const express = require("express");
const mysql = require("mysql2");
var cors = require("cors");
const cors = require("cors");
const bodyParser = require("body-parser");

// Create the Express app
const app = express();
app.use(cors());
app.use(bodyParser.json());

// Create a connection to the MySQL database
// MySQL connection config
const mysqlConfig = {
host: process.env.DB_HOST || "db",
host: process.env.DB_HOST || "mysql",
port: process.env.DB_PORT || "3306",
user: process.env.DB_USER || "root",
password: process.env.DB_PASSWORD || "pass123",
database: process.env.DB_NAME || "appdb",
};

let con = null;
const databaseInit = () => {
let con;

// Try connecting with retry logic (useful when DB takes time to start)
const connectWithRetry = (attempt = 1) => {
console.log(`Attempting to connect to DB... (try ${attempt})`);
con = mysql.createConnection(mysqlConfig);

con.connect((err) => {
if (err) {
console.error("Error connecting to the database: ", err);
return;
console.error("❌ DB connection failed:", err.message);
// Try again after 3 seconds
setTimeout(() => connectWithRetry(attempt + 1), 3000);
} else {
console.log("✅ Connected to MySQL database");
initDatabase(); // Create DB and table if missing
}
console.log("Connected to the database");
});
};

const createDatabase = () => {
con.query("CREATE DATABASE IF NOT EXISTS appdb", (err, results) => {
if (err) {
console.error(err);
return;
}
console.log("Database created successfully");
});
};
// Initialize DB and table
const initDatabase = () => {
con.query("CREATE DATABASE IF NOT EXISTS appdb", (err) => {
if (err) return console.error("Error creating DB:", err.message);
console.log("✅ Database ensured");

const createTable = () => {
con.query(
"CREATE TABLE IF NOT EXISTS apptb (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))",
(err, results) => {
if (err) {
console.error(err);
return;
}
console.log("Table created successfully");
}
);
// Switch to database
con.changeUser({ database: "appdb" }, (err) => {
if (err) return console.error("Error switching DB:", err.message);

con.query(
`CREATE TABLE IF NOT EXISTS apptb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
)`,
(err) => {
if (err) console.error("Error creating table:", err.message);
else console.log("✅ Table ensured");
}
);
});
});
};

// GET request
// Routes
app.get("/user", (req, res) => {
databaseInit();
con.query("SELECT * FROM apptb", (err, results) => {
if (err) {
console.error(err);
console.error("Error fetching data:", err);
res.status(500).send("Error retrieving data from database");
} else {
res.json(results);
}
});
});

// POST request
app.post("/user", (req, res) => {
con.query(
"INSERT INTO apptb (name) VALUES (?)",
[req.body.data],
(err, results) => {
if (err) {
console.error(err);
res.status(500).send("Error retrieving data from database");
} else {
res.json(results);
}
const { data } = req.body;
con.query("INSERT INTO apptb (name) VALUES (?)", [data], (err, results) => {
if (err) {
console.error("Error inserting data:", err);
res.status(500).send("Error inserting data");
} else {
res.json(results);
}
);
});

app.post("/dbinit", (req, res) => {
databaseInit();
createDatabase();
res.json("Database created successfully");
});

app.post("/tbinit", (req, res) => {
databaseInit();
createTable();
res.json("Table created successfully");
});
});

// Start the server
// Start server
app.listen(3000, () => {
console.log("Server running on port 3000");
console.log("🚀 Server running on port 3000");
connectWithRetry(); // Start DB connection with retry logic
});

58 changes: 32 additions & 26 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
version: "3.8"

services:
db: # Defines the 'db' service for MySQL database
image: mysql:8.0 # Uses the MySQL 8.0 Docker image
environment: # Sets environment variables for the database configuration
- MYSQL_DATABASE=appdb # Specifies the name of the database
- MYSQL_PASSWORD=pass123 # Sets the password for the MySQL user
- MYSQL_ROOT_PASSWORD=pass123 # Sets the root password for MySQL
mysql:
restart: always
image: mysql
environment:
- MYSQL_DATABASE=appdb
- MYSQL_PASSWORD=pass123
- MYSQL_ROOT_PASSWORD=pass123
networks:
- sameNetworkAsMysql # Connects the service to the 'sameNetworkAsMysql' network
ports:
- 3307:3306 # Maps the container's port 3306 to the host's port 3307
- project-net
volumes:
- ./script.sql:/docker-entrypoint-initdb.d/script.sql
- ./mysql-db:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -ppass123 || exit 1"]
interval: 10s
retries: 5
start_period: 30s

api: # Defines the 'api' service for the backend API
build: # Builds the backend API using the provided Dockerfile
context: ./backend # Specifies the build context directory for the backend
dockerfile: Dockerfile # Specifies the Dockerfile to use for building the backend
backend:
build:
context: ./backend
ports:
- 3000:3000 # Maps the container's port 3000 to the host's port 3000
- "3000:3000"
networks:
- sameNetworkAsMysql # Connects the service to the 'sameNetworkAsMysql' network
- project-net
depends_on:
- db # Specifies that the 'api' service depends on the 'db' service
mysql:
condition: service_healthy

frontend: # Defines the 'frontend' service for the frontend app
restart: on-failure # Restarts the container if it fails
build: # Builds the frontend app using the provided Dockerfile
context: ./frontend # Specifies the build context directory for the frontend
frontend:
restart: on-failure
build:
context: ./frontend
ports:
- 3001:3000 # Maps the container's port 3000 to the host's port 3001
- "3001:3000"
networks:
- sameNetworkAsMysql # Connects the service to the 'sameNetworkAsMysql' network
- project-net
depends_on:
- api # Specifies that the 'frontend' service depends on the 'api' service
- backend


networks:
sameNetworkAsMysql: # Defines the 'sameNetworkAsMysql' network
driver: bridge # Specifies the network driver as 'bridge'
project-net:
volumes:
mysql-db:
12 changes: 2 additions & 10 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
# Use the official Node.js 20 image as the base image
FROM node:20
FROM node

# Set the working directory in the container
WORKDIR /app

# Copy the package.json and package-lock.json files to the container
COPY package*.json ./

# Install the dependencies
RUN npm install

# Copy the rest of the application's source code to the container
COPY . .
COPY . .

# Build the React.js application
RUN npm run build

# Expose the port that the application listens on
EXPOSE 3001

# Start a simple web server to serve the built React.js files
CMD [ "npx", "serve", "-s", "build" ]