π οΈ Prerequisites
Before installing anything, verify your system meets the requirements and that the necessary ports are free. Skipping this step causes the most common installation failures.
π Concepts to Understand Firstβ
What Is a Scrape Target?β
Prometheus collects metrics by visiting a URL like http://your-app:3001/metrics on a schedule. This URL must exist and return data in Prometheus format. This is called a "scrape target."
What Is a Label?β
A label is a key-value tag attached to data. For example:
{app="healthtune", level="error", host="gcp-vm-1"}
Labels let you filter and group your data in Grafana queries.
What Is a Docker Volume?β
A folder inside Docker that persists data even when containers restart or are deleted. Without volumes, all your metrics/logs/traces would vanish every time you run docker compose down.
π» System Requirementsβ
Minimum (Dev / Testing)β
| Resource | Minimum |
|---|---|
| CPU | 2 vCPU |
| RAM | 4 GB |
| Disk | 20 GB free |
| OS | Ubuntu 20.04+ / Debian 11+ / Any Linux |
Recommended (Production with multiple apps)β
| Resource | Recommended |
|---|---|
| CPU | 4+ vCPU |
| RAM | 8+ GB |
| Disk | 50+ GB (metrics + logs grow fast) |
| OS | Ubuntu 22.04 LTS |
π‘ The Grafana stack is more RAM-efficient than ELK but Prometheus TSDB and Loki can grow. Set up data retention policies early (covered in Future Improvements).
π Check If Required Ports Are Freeβ
This is the most important pre-install step. Two services cannot share the same port.
Linux / Ubuntuβ
Check all stack ports at once:
sudo ss -ltnp | egrep ':(3000|9090|3100|3200|4317|4318|9100|9080)\b' || echo "All ports free"
Check individual ports:
sudo ss -ltnp | grep ':3000' # Grafana
sudo ss -ltnp | grep ':9090' # Prometheus
sudo ss -ltnp | grep ':3100' # Loki
sudo ss -ltnp | grep ':3200' # Tempo
sudo ss -ltnp | grep ':4317' # OTEL gRPC
sudo ss -ltnp | grep ':4318' # OTEL HTTP
sudo ss -ltnp | grep ':9100' # Node Exporter
π’ No output = port is free β good, proceed π΄ Output appears = port is in use β note which service owns it
Find out what's using a specific port:
sudo ss -ltnp | grep ':3000'
# Output shows the process name and PID
# Example: users:(("grafana",pid=1234,fd=6))
Windows (PowerShell β run as Administrator)β
$ports = @(3000, 9090, 3100, 3200, 4317, 4318, 9100, 9080)
foreach ($port in $ports) {
$result = netstat -ano | Select-String ":$port\s"
if ($result) {
Write-Host "Port $port IN USE:" -ForegroundColor Red
Write-Host $result
} else {
Write-Host "Port $port FREE" -ForegroundColor Green
}
}
Find which app owns a port (get the PID first from above, then):
# Replace 1234 with actual PID from netstat output
Get-Process -Id 1234 | Select-Object Name, Id
macOSβ
for port in 3000 9090 3100 3200 4317 4318 9100 9080; do
result=$(lsof -i :$port 2>/dev/null)
if [ -n "$result" ]; then
echo "Port $port IN USE: $result"
else
echo "Port $port FREE"
fi
done
π§ Resolving Port Conflictsβ
If a port is already taken, you have two options:
Option 1 β Change the conflicting service's port (if it's one of your own services)
Option 2 β Change the stack tool's host port in docker-compose.yaml
Port mapping format in Docker Compose is always HOST_PORT:CONTAINER_PORT.
The left side (host) is what you change. The right side (container) stays the same.
Example β if port 3000 is already used by another app, change Grafana to 3001:
# In docker-compose.yaml, Grafana service:
ports:
- "3001:3000" # Changed host port from 3000 to 3001
Then access Grafana at http://localhost:3001 instead.
π³ Install Dockerβ
Ubuntu / Debian (Linux)β
# Update packages
sudo apt update
# Install Docker
sudo apt install -y docker.io
# Enable and start Docker service
sudo systemctl enable docker
sudo systemctl start docker
# Add your user to docker group (avoid sudo every time)
sudo usermod -aG docker $USER
# Apply the group change in current terminal session
newgrp docker
# Verify
docker --version
docker run hello-world
Ubuntu β Install Docker Engine (Official method, newer)β
# Remove old versions if any
sudo apt remove docker docker-engine docker.io containerd runc
# Install prerequisites
sudo apt update
sudo apt install -y ca-certificates curl gnupg
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Add repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine + Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Verify
docker --version
docker compose version
Windowsβ
- Download Docker Desktop from docker.com/products/docker-desktop
- Run the installer β it installs both Docker and Docker Compose
- Start Docker Desktop from the Start Menu
- Open PowerShell and verify:
docker --version
docker compose version
π‘ On Windows, Docker Desktop uses WSL2 (Windows Subsystem for Linux) under the hood. Make sure WSL2 is enabled β the Docker installer usually handles this.
macOSβ
# Using Homebrew
brew install --cask docker
# Start Docker Desktop from Applications
# Then verify:
docker --version
docker compose version
π Verify Docker Composeβ
# New style (v2, built-in plugin)
docker compose version
# Expected: Docker Compose version v2.x.x
# Old style (v1, separate binary β still works)
docker-compose --version
Both work. This guide uses
docker compose(no hyphen) which is the current standard.
π¦ Install Gitβ
Linuxβ
sudo apt install -y git
git --version
Windowsβ
Download from git-scm.com and install. Then verify in PowerShell:
git --version
macOSβ
# Git comes with Xcode command line tools
xcode-select --install
# Or via Homebrew:
brew install git
π Pre-Installation Checklistβ
Run through this entirely before starting the install:
# 1. Docker running?
docker --version && docker info | grep "Server Version"
# 2. Docker Compose available?
docker compose version
# 3. Git available?
git --version
# 4. Disk space available? (need at least 5 GB free for images)
df -h /
# 5. RAM available?
free -h
# 6. All ports free?
sudo ss -ltnp | egrep ':(3000|9090|3100|3200|4317|4318|9100)\b' || echo "All clear"
Everything checks out? Move on to Install Prometheus β