Skip to content

Instantly share code, notes, and snippets.

@si3mshady
Last active March 28, 2025 10:16
Show Gist options
  • Save si3mshady/fde684c7b094e4ee95a05bbf50b1d561 to your computer and use it in GitHub Desktop.
Save si3mshady/fde684c7b094e4ee95a05bbf50b1d561 to your computer and use it in GitHub Desktop.
This script automates the setup and deployment of four AI-powered web applications (meal suggestions, drink recipes, workout plans, and nutrition analysis) along with monitoring tools (Prometheus and Grafana). Each application integrates with the OpenAI API for AI-generated results, and Prometheus collects metrics for observability.
#!/bin/bash
DOCKER_USERNAME="si3mshady"
API_KEY="your_openai_api_key_here" # Replace with your actual OpenAI API key
# Create the project directory structure
mkdir -p prometheus grafana
mkdir -p meal_app/public drink_app/public workout_app/public nutrition_app/public
# Create Prometheus configuration file
cat <<EOF > prometheus/prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'meal-app'
static_configs:
- targets: ['meal-app:5001']
- job_name: 'drink-app'
static_configs:
- targets: ['drink-app:5002']
- job_name: 'workout-app'
static_configs:
- targets: ['workout-app:5003']
- job_name: 'nutrition-app'
static_configs:
- targets: ['nutrition-app:5004']
EOF
# Create Docker Compose configuration
cat <<EOF > docker-compose.yml
version: '3.8'
services:
meal-app:
image: $DOCKER_USERNAME/meal-app:latest
build:
context: ./meal_app
ports:
- "5001:5001"
drink-app:
image: $DOCKER_USERNAME/drink-app:latest
build:
context: ./drink_app
ports:
- "5002:5002"
workout-app:
image: $DOCKER_USERNAME/workout-app:latest
build:
context: ./workout_app
ports:
- "5003:5003"
nutrition-app:
image: $DOCKER_USERNAME/nutrition-app:latest
build:
context: ./nutrition_app
ports:
- "5004:5004"
prometheus:
image: prom/prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
EOF
# Function to create application files
create_app() {
APP_NAME=$1
PORT=$2
AI_PROMPT=$3
HANDLER_PATH=$4
mkdir -p $APP_NAME/public
# Create package.json
cat <<EOF > $APP_NAME/package.json
{
"name": "$APP_NAME",
"version": "1.0.0",
"main": "app.js",
"dependencies": {
"express": "^4.17.1",
"prom-client": "^14.0.0",
"body-parser": "^1.19.0",
"node-fetch": "^2.6.7"
}
}
EOF
# Create Dockerfile
cat <<EOF > $APP_NAME/Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE $PORT
CMD ["node", "app.js"]
EOF
# Create app.js
cat <<EOF > $APP_NAME/app.js
const express = require('express');
const fetch = require('node-fetch');
const promClient = require('prom-client');
const bodyParser = require('body-parser');
const app = express();
const port = $PORT;
// Prometheus metrics
const register = new promClient.Registry();
promClient.collectDefaultMetrics({ register });
const requestCounter = new promClient.Counter({
name: '${APP_NAME}_requests_total',
help: 'Total number of requests',
registers: [register],
});
// Middleware
app.use(bodyParser.json());
app.use(express.static('public'));
// Routes
app.post('${HANDLER_PATH}', async (req, res) => {
requestCounter.inc();
const { input } = req.body;
try {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: \`Bearer ${API_KEY}\`,
},
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: \`${AI_PROMPT} \${input}\` }],
max_tokens: 150,
}),
});
const data = await response.json();
if (data.choices && data.choices[0]?.message?.content) {
res.json({ result: data.choices[0].message.content });
} else {
console.error('Unexpected API response:', data);
res.status(500).json({ error: 'Unexpected API response format.' });
}
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: 'An error occurred while processing your request.' });
}
});
// Metrics endpoint
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
app.listen(port, () => {
console.log('${APP_NAME} is running at http://localhost:${PORT}');
});
EOF
# Create public/index.html
cat <<EOF > $APP_NAME/public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${APP_NAME}</title>
</head>
<body>
<h1>${APP_NAME}</h1>
<form id="form">
<label for="input">Enter Input:</label>
<input type="text" id="input" name="input" required>
<button type="submit">Submit</button>
</form>
<div id="result"></div>
<script>
document.getElementById('form').addEventListener('submit', async (e) => {
e.preventDefault();
const input = document.getElementById('input').value;
const response = await fetch('${HANDLER_PATH}', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ input }),
});
const data = await response.json();
document.getElementById('result').innerText = data.result || 'No response';
});
</script>
</body>
</html>
EOF
}
# Create applications
create_app "meal_app" 5001 "Suggest a healthy meal for the following ingredients:" "/meal"
create_app "drink_app" 5002 "Suggest a healthy drink recipe for the following ingredients:" "/drink"
create_app "workout_app" 5003 "Create a targeted workout plan for the following body part:" "/workout"
create_app "nutrition_app" 5004 "Estimate the calories and nutrition for the following food description:" "/nutrition"
# Build, tag, and push Docker images
for app in meal_app drink_app workout_app nutrition_app; do
docker build -t $DOCKER_USERNAME/$app:latest $app
docker push $DOCKER_USERNAME/$app:latest
done
echo "Setup complete. Run 'docker-compose up' to start all services."
@si3mshady
Copy link
Author

updated prom config

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment