- Wed Mar 19 2025
- 3 minutes
Docker Logs Observability Using Grafana
Managing logs is a developer’s responsibility—never be caught off guard when asked, “Where’s the error?” 😆 If you’re managing a single-instance container on a VPS, this article is for you. We’ll implement a simple yet effective solution that eliminates the need to log in via SSH just to check logs. With this setup, you can go beyond just viewing logs—you’ll be able to create dashboards, track metrics, perform searches, and even set up alerts.
Advantages of This Approach
With this setup, you don’t have to worry about managing log files, retention, or storage on your application. Simply log to the console, and Promtail will automatically collect and send the logs to Loki. But remember, you have to follow logging best practices to maximize the benefits of this observability stack:
- Use appropriate logging levels (INFO, WARN, ERROR, etc.).
- Write structured and meaningful log messages.
- Keep logs concise, avoid excessive logging to prevent noise.
- Never expose sensitive information in logs.
Why Use Grafana?
Grafana is a powerful open-source tool for monitoring, visualizing, and analyzing logs and metrics. It allows you to turn raw log data into meaningful insights with interactive dashboards. Unlike traditional log viewing methods that require manual SSH access, Grafana provides a centralized interface to track system performance and detect anomalies in real-time.
However, Grafana alone is not enough for log observability. We need a complete stack that includes:
- Grafana: The visualization and dashboard tool that helps you explore log data and set up alerts.
- Loki: A log aggregation system designed for efficiency and scalability, acting as a backend for storing and indexing logs.
- Promtail: A lightweight log collector that ships logs from Docker containers to Loki.
All three components can run on Docker. In the next section, I’ll provide a simple Docker Compose setup to deploy them easily.
But before that, you need to configure Loki and Promtail. Here is the configuration for Loki.
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
log_level: debug
grpc_server_max_concurrent_streams: 1000
common:
instance_addr: 127.0.0.1
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
limits_config:
metric_aggregation_enabled: true
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
pattern_ingester:
enabled: true
metric_aggregation:
loki_address: localhost:3100
ruler:
alertmanager_url: http://localhost:9093
frontend:
encoding: protobuf
# By default, Loki will send anonymous, but uniquely-identifiable usage and configuration
# analytics to Grafana Labs. These statistics are sent to https://stats.grafana.org/
#
# Statistics help us better understand how Loki is used, and they show us performance
# levels for most users. This helps us prioritize features and documentation.
# For more information on what's sent, look at
# https://github.com/grafana/loki/blob/main/pkg/analytics/stats.go
# Refer to the buildReport method to see what goes into a report.
#
# If you would like to disable reporting, uncomment the following lines:
#analytics:
# reporting_enabled: false
Save this configuration somewhere on your server. Next, create a Promtail configuration to collect Docker logs and send them to Loki.
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: docker-logs
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: [__meta_docker_container_name]
target_label: container
- source_labels: [__meta_docker_image]
target_label: image
Next, create the Docker Compose configuration.
version: "3.3"
networks:
loki:
services:
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml
networks:
- loki
promtail:
image: grafana/promtail:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
networks:
- loki
grafana:
environment:
- GF_PATHS_PROVISIONING=/etc/grafana/provisioning
- GF_AUTH_ANONYMOUS_ENABLED=false
- GF_FEATURE_TOGGLES_ENABLE=alertingSimplifiedRouting,alertingQueryAndExpressionsStepMode
entrypoint:
- sh
- -euc
- |
mkdir -p /etc/grafana/provisioning/datasources
cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
orgId: 1
url: http://loki:3100
basicAuth: false
isDefault: true
version: 1
editable: false
EOF
/run.sh
image: grafana/grafana:latest
ports:
- "3000:3000"
networks:
- loki
Fire up all three services with the following command:
docker-compose up -d
You can verify that Loki is up and running.
- To view readiness, navigate to http://your-server-ip:3100/ready.
- To view metrics, navigate to http://your-server-ip:3100/metrics.
Next, you can access Grafana by opening http://your-server-ip:3000 in your browser. By default, the login credentials are:
- Username: admin
- Password: admin
Upon your first login, Grafana will prompt you to change the password for security reasons. Once inside, you can start adding Loki as a data source and explore your logs in a more interactive way. 🚀