Centralizing Logs with Grafana Loki & Promtail
This quickstart guides you through deploying Grafana Loki, Promtail, and Grafana utilizing Docker Compose, establishing an automated pipeline to ship and query localized infrastructure logs.
As of March 2, 2026, Grafana Labs has officially designated the Promtail agent as End of Life (EOL). Commercial support has fully terminated, and no future maintenance updates will be provided. All active feature development has transitioned entirely to Grafana Alloy.
If you are maintaining production instances or spinning up new environments, Grafana strongly recommends migrating from Promtail to Alloy. This quickstart retains Promtail purely for legacy local evaluation workflows; do not mirror this topology in modern infrastructures.
1. Core Concepts
- Grafana Loki: A horizontally scalable, highly available, tenant-aware log aggregation engine. Unlike Elasticsearch, Loki only indexes metadata labels (such as
joborcontainer) and leaves the raw log lines compressed, drastically minimizing memory footprint and operational overhead. - Promtail: The native shipping agent. It discovers log targets, attaches matching metadata labels, and pushes micro-batches directly to the Loki cluster.
- Grafana: The unified visualization layer. It executes LogQL queries against Loki data streams to build real-time analytical dashboards.
Promtail discovers local logs, labels them, and pushes batches into Loki. Grafana then queries those streams with LogQL.
This guide assumes you are using Linux.
2. Orchestration Infrastructure Setup
Create an isolated working directory on your workstation to house the infrastructure manifests:
mkdir loki-quickstart && cd loki-quickstart
Deploying this stack requires two companion configurations. Use the interactive tabs below to examine and provision the ecosystem files in your workspace directory:
- docker-compose.yaml
- promtail-config.yaml
services:
loki:
image: grafana/loki:3.6.11
command: -config.file=/etc/loki/local-config.yaml
ports:
- "127.0.0.1:3101:3100"
volumes:
- loki-data:/tmp/loki
promtail:
image: grafana/promtail:3.6.11
command: -config.file=/etc/promtail/config.yml
volumes:
- ./promtail-config.yaml:/etc/promtail/config.yml:ro
- /var/log:/var/log:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- promtail-positions:/tmp
depends_on:
- loki
grafana:
image: grafana/grafana:12.4.13
ports:
- "127.0.0.1:3200:3000"
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- loki
volumes:
loki-data:
promtail-positions:
grafana-data:
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*log
- job_name: containers
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ["__meta_docker_container_name"]
regex: "/(.*)"
target_label: container
- source_labels: ["__meta_docker_container_log_stream"]
target_label: stream
The Docusaurus local development server and the default Grafana core instance both bind to ingress port 3000 by default. Running them concurrently will cause a network socket allocation failure. To resolve this, this topology maps Grafana's external port to host port 3200. Access the visualization dashboard interface at http://localhost:3200 while keeping your local documentation workspace cleanly isolated on port 3000.
Loki publishes on host port 3101 (http://localhost:3101). Both ingress interfaces are bounded to loopback 127.0.0.1. Promtail mounts the host's Docker socket read-only to monitor engine events. Ensure this stack runs strictly within controlled local dev zones.
Execute the initialization sequence to spin up the container network in detached mode:
docker compose up -d
Verify that the log aggregation engine has stabilized and is actively accepting write streams:
curl -sS http://localhost:3101/ready
3. Registering the Loki Data Source
- Navigate to the Grafana control panel at http://localhost:3200.
- Authenticate using the default credentials:
admin/admin. Update the primary credentials when prompted. - In the left-hand navigation sidebar, click Connections, then select Data sources.
- Click Add new data source, and select Loki from the analytics catalog.
- Configure the HTTP Connection URL parameter exactly to:
http://loki:3100. - Click Save & test to validate the connection lifecycle.
Do not utilize http://localhost:3101 from the Grafana settings interface. Inside the isolated container space, localhost resolves internally to Grafana itself, rather than the host machine. Setting it to the service alias http://loki:3100 utilizes Docker's internal DNS routing seamlessly.
4. Querying Logs via LogQL
To execute an initial validation smoke test against host system logs, manually inject a sample error entry into your local log architecture:
echo "error: loki quickstart sample" | sudo tee -a /var/log/syslog
- In the primary navigation pane, select Explore.
- Select the newly provisioned Loki data source from the dropdown selector.
- Toggle the query input component to Code mode.
- Execute the following baseline metadata label search:
{job="varlogs"}
- Adjust the target time window parameter to Last 15 minutes and click Run query.
To filter out noise from heavy log streams without indexing raw text contents, append a case-sensitive substring filter expression utilizing the |= operator:
{job="varlogs"} |= "error"
Loki streams the initial chunk filtered by the varlogs index label, then executes high-velocity text scanning over the matching results in real time.
To audit container-specific logs discovered via Promtail's engine socket wrapper, spin up a test container and run a LogQL streams query targeting the container metadata label:
docker run --name log-demo alpine echo "error: sample application failure"
{job="containers", container="log-demo"} |= "error"
Clean up the transient evaluation footprint when finalized:
docker rm log-demo
Official References & Documentation Standards: