A production-ready Docker environment for Laravel 12 (PHP 8.4) integrated with a full Observability stack. This project monitors application performance, infrastructure health, and logs using Grafana, Prometheus and Loki.
- App: Laravel 12 running on PHP 8.4 (via Laravel Sail).
- Database: MySQL 8.0.
- Metrics:
- Prometheus: Scrapes metrics from the app and infrastructure.
- Laravel Exporter: Custom instrumentation for Database Query timing.
- Logs:
- Promtail: tails
storage/logs/laravel.logand pushes to Loki. - Loki: Stores logs for querying.
- Promtail: tails
- Visualization: Grafana.
Ensure your project config files match this structure for the stack to function correctly:
/laravel-grafana
├── docker-compose.yml
├── .env
├── .docker/
│ ├── 8.4/ # Custom PHP 8.4 Dockerfile & configs
│ └── config/ # Observability Configs
│ ├── grafana.ini
│ ├── local-config.yaml (Loki)
│ ├── prometheus.yml
│ └── promtail.yaml
└── storage/
└── logs/ # Mounted to Promtail
-
Clone the repository and enter the directory.
-
Environment Setup:
cp .env.example .env
Ensure
DB_HOST=mysqlandDB_CONNECTION=mysql. -
Start the Stack: This command builds the custom PHP 8.4 image and starts all monitoring containers.
./vendor/bin/sail up -d --build
-
Install Dependencies & Migrate:
./vendor/bin/sail composer run setup ./vendor/bin/sail artisan migrate:fresh --seed
| Service | Local Address | Internal Docker Address | Description |
|---|---|---|---|
| Laravel App | http://localhost:80 |
laravel.test:80 |
Main Application |
| Grafana | http://localhost:3000 |
grafana:3000 |
Dashboards (Login: admin/admin) |
| Prometheus | http://localhost:9090 |
prometheus:9090 |
Metrics Scraper |
| Loki | http://localhost:3100 |
loki:3100 |
Log Aggregation API |
| MySQL | localhost:3306 |
mysql:3306 |
Database |
- Login to Grafana at http://localhost:3000 (Default:
admin/admin). - Go to Connections
$\rightarrow$ Data Sources$\rightarrow$ Add new data source.
- Name: Loki
- URL:
http://loki:3100(Note: Do not use localhost) - Click Save & Test.
- Name: Prometheus
- URL:
http://prometheus:9090 - Click Save & Test.
To debug application errors:
- Go to Explore (Compass Icon) in Grafana.
- Select Loki from the dropdown.
- Filter by job:
{job="laravel"}. - Click Run Query to see real-time logs from
storage/logs/laravel.log.
To see how long SQL queries are taking:
- Go to Explore and select Prometheus.
- Use the following PromQL queries:
- 95th Percentile Query Latency:
histogram_quantile(0.95, sum(rate(laravel_database_query_duration_seconds_bucket[5m])) by (le)) - Queries Per Second:
sum(rate(laravel_database_query_duration_seconds_count[1m]))
- 95th Percentile Query Latency:
This stack uses Named Volumes to persist data even if containers are stopped.
- Database:
sail-mysql - Logs (Loki):
loki-data - Metrics (Prometheus):
prometheus-data - Grafana Settings:
grafana-data
To Reset Everything (Caution): If you want to wipe the database and all metrics/logs to start fresh:
./vendor/bin/sail down -v(The -v flag deletes all volumes).
"Loki: Ingester not ready"
- Loki takes 30–60 seconds to initialize its storage ring on startup. Wait a minute and refresh. "Laravel Logs not showing in Grafana"
- Ensure the
storage/logsdirectory has read permissions. - Check Promtail logs:
docker-compose logs -f promtail.
"Metrics page is empty"
- Visit
http://localhost/prometheus. If it's empty, ensure you have hit the application (http://localhost) at least once to generate traffic.