Ingesting Docker logs into Loki sends container stdout and stderr to a queryable log backend without changing application code. The Loki Docker driver attaches to Docker Engine as a logging plugin and forwards selected container logs to a Loki push endpoint.
The plugin is installed on each Docker host that runs containers whose logs should be shipped. The Loki URL must be reachable from the Docker host, not from inside the application container, and plugin installation changes host Docker state.
Use this path for Docker Engine hosts where a logging driver is acceptable. For Kubernetes, systemd journals, files, or richer parsing pipelines, use Grafana Alloy or another log collector instead of the Docker logging driver.
Steps to ingest Docker logs into Loki:
- Confirm Loki is reachable from the Docker host.
$ curl --silent http://127.0.0.1:3100/ready ready
- Install the Loki Docker driver plugin.
$ docker plugin install grafana/loki-docker-driver:3.7.0-amd64 \ --alias loki \ --grant-all-permissions Plugin "grafana/loki-docker-driver:3.7.0-amd64" is requesting the following privileges: - network: [host] - mount: [/var/log] ##### snipped ##### Installed plugin grafana/loki-docker-driver:3.7.0-amd64
Docker plugins are host-level Docker Engine extensions. Install them only on hosts where plugin privileges and lifecycle are approved.
- Confirm the plugin is enabled.
$ docker plugin ls ID NAME DESCRIPTION ENABLED 4b921d7f4c2a loki Loki Logging Driver true
- Start a test container with the Loki logging driver.
$ docker run --rm \ --log-driver=loki \ --log-opt loki-url=http://127.0.0.1:3100/loki/api/v1/push \ --log-opt loki-external-labels=job=docker-smoke,service_name=checkout-api \ alpine:3.22 \ sh -c 'echo "checkout complete trace_id=5b8efff798038103d269b633813fc700"' checkout complete trace_id=5b8efff798038103d269b633813fc700
The label set should stay small and stable. Put request IDs and trace IDs in the log line or structured metadata instead of labels.
- Query Loki for the test container log.
$ curl --silent --get http://127.0.0.1:3100/loki/api/v1/query_range \ --data-urlencode 'query={service_name="checkout-api"} |= "checkout complete"' \ --data-urlencode limit=5 { "status": "success", "data": { "resultType": "streams", "result": [ { "stream": { "job": "docker-smoke", "service_name": "checkout-api" }, "values": [ [ "1782008380038503000", "checkout complete trace_id=5b8efff798..." ] ] } ] } } - Configure the logging driver for a Compose service when the test query works.
- compose.yaml
services: checkout: image: alpine:3.22 command: sh -c 'while true; do echo "checkout heartbeat"; sleep 30; done' logging: driver: loki options: loki-url: http://127.0.0.1:3100/loki/api/v1/push loki-external-labels: job=checkout,service_name=checkout-api
- Start the Compose service.
$ docker compose up -d checkout Container app-checkout-1 Started
- Query the Compose service labels in Loki.
$ curl --silent --get http://127.0.0.1:3100/loki/api/v1/query_range \ --data-urlencode 'query={job="checkout",service_name="checkout-api"}' \ --data-urlencode limit=5 { "status": "success", "data": { "resultType": "streams", "result": [ { "stream": { "job": "checkout", "service_name": "checkout-api" }, "values": [ [ "1782008400000000000", "checkout heartbeat" ] ] } ] } } - Remove the plugin only when no container still uses it.
$ docker plugin disable loki --force loki $ docker plugin rm loki loki
Disabling the plugin can interrupt log shipping for containers configured to use the loki logging driver.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.