🛠️ 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 →