How to Self-Host Promtail with Docker Compose
What Is Promtail?
Promtail is Grafana’s log collection agent designed to ship logs to Loki. It discovers log files, attaches labels, and pushes entries to Loki’s API. Think of it as the “Prometheus of logs” — it tails files and streams them to your central log store. Promtail entered LTS in early 2026; Grafana recommends Grafana Alloy for new deployments, but Promtail remains widely used and fully functional.
Updated March 2026: Verified with latest Docker images and configurations.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- A running Loki instance (Loki setup guide)
- 512 MB of free RAM
- Basic understanding of your log file locations
Docker Compose Configuration
This deploys Promtail alongside Loki and Grafana as a complete logging stack. If you already have Loki running, use only the promtail service.
Create a docker-compose.yml file:
services:
loki:
image: grafana/loki:3.6.7
container_name: loki
ports:
- "3100:3100"
volumes:
- loki_data:/loki
command: -config.file=/etc/loki/local-config.yaml
restart: unless-stopped
promtail:
image: grafana/promtail:3.6.7
container_name: promtail
volumes:
- ./promtail-config.yml:/etc/promtail/config.yml:ro
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- promtail_positions:/tmp
command: -config.file=/etc/promtail/config.yml
depends_on:
- loki
restart: unless-stopped
grafana:
image: grafana/grafana:12.4.1
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=changeme # CHANGE THIS
restart: unless-stopped
volumes:
loki_data:
promtail_positions:
grafana_data:
Create a promtail-config.yml file alongside:
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:
# System logs
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: syslog
__path__: /var/log/syslog
# Auth logs
- job_name: auth
static_configs:
- targets:
- localhost
labels:
job: auth
__path__: /var/log/auth.log
# Docker container logs
- job_name: docker
static_configs:
- targets:
- localhost
labels:
job: docker
__path__: /var/lib/docker/containers/*/*-json.log
pipeline_stages:
- json:
expressions:
log: log
stream: stream
time: time
- labels:
stream:
- timestamp:
source: time
format: RFC3339Nano
- output:
source: log
Start the stack:
docker compose up -d
Initial Setup
- Verify Promtail is running and connected to Loki:
docker compose logs promtail
You should see lines like Starting Promtail and Sending batch — no connection errors.
-
Open Grafana at
http://your-server:3000(default login:admin/changeme). -
Add Loki as a data source:
- Go to Connections → Data Sources → Add data source
- Select Loki
- Set URL to
http://loki:3100 - Click Save & Test
-
Go to Explore, select the Loki data source, and query
{job="syslog"}to see system logs flowing in.
Configuration
Scrape Config Structure
Each scrape_config defines a log source with three key parts:
| Component | Purpose |
|---|---|
job_name | Label for this log source |
static_configs | File paths and labels to attach |
pipeline_stages | Optional log parsing and transformation |
Adding Custom Log Sources
To collect logs from a specific application (e.g., Nginx):
scrape_configs:
- job_name: nginx
static_configs:
- targets:
- localhost
labels:
job: nginx
type: access
__path__: /var/log/nginx/access.log
- targets:
- localhost
labels:
job: nginx
type: error
__path__: /var/log/nginx/error.log
Mount the log directory in your Docker Compose:
promtail:
volumes:
- /var/log/nginx:/var/log/nginx:ro
Pipeline Stages
Pipeline stages parse and transform log lines before sending to Loki:
pipeline_stages:
# Parse JSON logs
- json:
expressions:
level: level
message: msg
timestamp: ts
# Add extracted values as labels
- labels:
level:
# Parse timestamps
- timestamp:
source: timestamp
format: "2006-01-02T15:04:05.000Z"
# Set the output line
- output:
source: message
Multi-Tenant Configuration
Route logs to different Loki tenants:
clients:
- url: http://loki:3100/loki/api/v1/push
tenant_id: infrastructure
- url: http://loki:3100/loki/api/v1/push
tenant_id: applications
Advanced Configuration (Optional)
Journal Scraping (systemd)
Collect logs from systemd journal instead of files:
scrape_configs:
- job_name: journal
journal:
max_age: 12h
labels:
job: systemd-journal
relabel_configs:
- source_labels: ['__journal__systemd_unit']
target_label: 'unit'
Requires mounting the journal directory:
volumes:
- /var/log/journal:/var/log/journal:ro
- /run/log/journal:/run/log/journal:ro
- /etc/machine-id:/etc/machine-id:ro
Regex Parsing for Unstructured Logs
Extract fields from plain text logs:
pipeline_stages:
- regex:
expression: '^(?P<ip>\S+) \S+ \S+ \[(?P<timestamp>[^\]]+)\] "(?P<method>\S+) (?P<path>\S+) \S+" (?P<status>\d+) (?P<size>\d+)'
- labels:
method:
status:
- timestamp:
source: timestamp
format: "02/Jan/2006:15:04:05 -0700"
Drop Noisy Logs
Filter out unwanted log lines to reduce storage:
pipeline_stages:
- drop:
expression: "healthcheck"
drop_counter_reason: "healthcheck_noise"
- drop:
expression: "GET /favicon.ico"
drop_counter_reason: "favicon_noise"
Reverse Proxy
Promtail’s HTTP API (port 9080) is typically internal-only. If you need to expose it:
location /promtail/ {
proxy_pass http://localhost:9080/;
proxy_set_header Host $host;
}
For reverse proxy setup details, see Reverse Proxy Setup.
Backup
Back up the positions file to preserve read offsets:
docker compose exec promtail cat /tmp/positions.yaml > promtail-positions-backup.yaml
The positions file tracks where Promtail left off in each log file. If lost, Promtail re-reads from the beginning of active files. For your full backup strategy, see Backup Strategy.
Troubleshooting
Promtail Not Sending Logs to Loki
Symptom: No data appears in Grafana when querying Loki. Fix: Check Promtail logs for connection errors:
docker compose logs promtail | grep -i error
Verify Loki is reachable from the Promtail container:
docker compose exec promtail wget -qO- http://loki:3100/ready
Permission Denied on Log Files
Symptom: permission denied errors for /var/log/ files.
Fix: Run Promtail as root or add the container user to the appropriate groups. In Docker Compose, add:
promtail:
user: root
Duplicate Log Entries After Restart
Symptom: Same log lines appear multiple times in Loki.
Fix: Ensure the positions volume is persistent. If promtail_positions is lost, Promtail re-reads all files from the start. Check:
docker volume inspect promtail_positions
High Memory Usage
Symptom: Promtail consuming excessive RAM. Fix: Reduce the number of active targets or add rate limiting:
limits_config:
readline_rate_enabled: true
readline_rate: 100
readline_burst: 1000
Docker Container Logs Not Appearing
Symptom: Docker logs not visible despite /var/lib/docker/containers being mounted.
Fix: Verify Docker’s log driver is json-file (the default). Other drivers like journald require different scraping:
docker info | grep "Logging Driver"
Resource Requirements
- RAM: 50-100 MB idle, 200-500 MB under heavy log volume
- CPU: Low — Promtail is I/O-bound, not CPU-bound
- Disk: Minimal — positions file is a few KB. Logs are stored in Loki, not Promtail.
Verdict
Promtail is the simplest path to getting logs into Loki. If you already run Loki and Grafana, Promtail is the natural collector — zero configuration friction, native label support, and pipeline stages handle most parsing needs. For new deployments, evaluate Grafana Alloy as the next-generation replacement — it handles logs, metrics, and traces in a single agent. For existing setups, Promtail works reliably and will receive LTS patches.
Frequently Asked Questions
Is Promtail being replaced by Grafana Alloy?
Yes. Grafana has announced that Promtail is in maintenance mode and recommends Grafana Alloy for new deployments. Alloy handles logs, metrics, and traces in a single agent. Existing Promtail setups will continue receiving security patches but no new features. If starting fresh, consider Alloy. If Promtail is already working, there’s no urgent need to migrate.
Can Promtail collect logs from Docker containers?
Yes. Mount /var/lib/docker/containers and /var/run/docker.sock into the Promtail container, then configure a Docker scrape target. Promtail reads container logs and adds labels for container name, image, and compose service. Docker must use the default json-file logging driver.
Does Promtail work without Loki?
No. Promtail is specifically designed to ship logs to Loki. It cannot send logs to Elasticsearch, Graylog, or other log backends. If you need a flexible log shipper that works with multiple backends, use Fluentd, Fluent Bit, or Vector instead.
How does Promtail handle log parsing?
Promtail uses pipeline stages for log processing. You can parse JSON, regex-match log lines, extract labels, add timestamps, drop unwanted lines, and transform values — all in the configuration file. Pipeline stages process logs before sending them to Loki, so you can structure and filter data at the source.
Can Promtail collect system logs (journald, syslog)?
Yes. Promtail supports journald and syslog as log sources alongside file-based scraping. For journald, configure a journal scrape config. For syslog, Promtail can listen on a UDP/TCP port as a syslog receiver. Mount /var/log/journal for journald access.
How much disk space does Promtail use?
Promtail uses virtually no disk space — it reads log files and streams them to Loki without storing copies. The only persistent data is a small positions file (a few KB) that tracks read offsets so Promtail can resume after restart. All log storage is in Loki, not Promtail.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments