Last active
March 28, 2025 10:16
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
updated prom config