| --- |
| title: Docker log driver plugins |
| description: "Log driver plugins." |
| keywords: "Examples, Usage, plugins, docker, documentation, user guide, logging" |
| --- |
| |
| This document describes logging driver plugins for Docker. |
| |
| Logging drivers enables users to forward container logs to another service for |
| processing. Docker includes several logging drivers as built-ins, however can |
| never hope to support all use-cases with built-in drivers. Plugins allow Docker |
| to support a wide range of logging services without requiring to embed client |
| libraries for these services in the main Docker codebase. See the |
| [plugin documentation](legacy_plugins.md) for more information. |
| |
| ## Create a logging plugin |
| |
| The main interface for logging plugins uses the same JSON+HTTP RPC protocol used |
| by other plugin types. See the |
| [example](https://github.com/cpuguy83/docker-log-driver-test) plugin for a |
| reference implementation of a logging plugin. The example wraps the built-in |
| `jsonfilelog` log driver. |
| |
| ## LogDriver protocol |
| |
| Logging plugins must register as a `LogDriver` during plugin activation. Once |
| activated users can specify the plugin as a log driver. |
| |
| There are two HTTP endpoints that logging plugins must implement: |
| |
| ### `/LogDriver.StartLogging` |
| |
| Signals to the plugin that a container is starting that the plugin should start |
| receiving logs for. |
| |
| Logs will be streamed over the defined file in the request. On Linux this file |
| is a FIFO. Logging plugins are not currently supported on Windows. |
| |
| Request: |
| |
| ```json |
| { |
| "File": "/path/to/file/stream", |
| "Info": { |
| "ContainerID": "123456" |
| } |
| } |
| ``` |
| |
| `File` is the path to the log stream that needs to be consumed. Each call to |
| `StartLogging` should provide a different file path, even if it's a container |
| that the plugin has already received logs for prior. The file is created by |
| Docker with a randomly generated name. |
| |
| `Info` is details about the container that's being logged. This is fairly |
| free-form, but is defined by the following struct definition: |
| |
| ```go |
| type Info struct { |
| Config map[string]string |
| ContainerID string |
| ContainerName string |
| ContainerEntrypoint string |
| ContainerArgs []string |
| ContainerImageID string |
| ContainerImageName string |
| ContainerCreated time.Time |
| ContainerEnv []string |
| ContainerLabels map[string]string |
| LogPath string |
| DaemonName string |
| } |
| ``` |
| |
| `ContainerID` will always be supplied with this struct, but other fields may be |
| empty or missing. |
| |
| Response: |
| |
| ```json |
| { |
| "Err": "" |
| } |
| ``` |
| |
| If an error occurred during this request, add an error message to the `Err` field |
| in the response. If no error then you can either send an empty response (`{}`) |
| or an empty value for the `Err` field. |
| |
| The driver should at this point be consuming log messages from the passed in file. |
| If messages are unconsumed, it may cause the container to block while trying to |
| write to its stdio streams. |
| |
| Log stream messages are encoded as protocol buffers. The protobuf definitions are |
| in the |
| [moby repository](https://github.com/moby/moby/blob/master/api/types/plugins/logdriver/entry.proto). |
| |
| Since protocol buffers are not self-delimited you must decode them from the stream |
| using the following stream format: |
| |
| ```text |
| [size][message] |
| ``` |
| |
| Where `size` is a 4-byte big endian binary encoded uint32. `size` in this case |
| defines the size of the next message. `message` is the actual log entry. |
| |
| A reference golang implementation of a stream encoder/decoder can be found |
| [here](https://github.com/docker/docker/blob/master/api/types/plugins/logdriver/io.go) |
| |
| ### `/LogDriver.StopLogging` |
| |
| Signals to the plugin to stop collecting logs from the defined file. |
| Once a response is received, the file will be removed by Docker. You must make |
| sure to collect all logs on the stream before responding to this request or risk |
| losing log data. |
| |
| Requests on this endpoint does not mean that the container has been removed |
| only that it has stopped. |
| |
| Request: |
| |
| ```json |
| { |
| "File": "/path/to/file/stream" |
| } |
| ``` |
| |
| Response: |
| |
| ```json |
| { |
| "Err": "" |
| } |
| ``` |
| |
| If an error occurred during this request, add an error message to the `Err` field |
| in the response. If no error then you can either send an empty response (`{}`) |
| or an empty value for the `Err` field. |
| |
| ## Optional endpoints |
| |
| Logging plugins can implement two extra logging endpoints: |
| |
| ### `/LogDriver.Capabilities` |
| |
| Defines the capabilities of the log driver. You must implement this endpoint for |
| Docker to be able to take advantage of any of the defined capabilities. |
| |
| Request: |
| |
| ```json |
| {} |
| ``` |
| |
| Response: |
| |
| ```json |
| { |
| "ReadLogs": true |
| } |
| ``` |
| |
| Supported capabilities: |
| |
| - `ReadLogs` - this tells Docker that the plugin is capable of reading back logs |
| to clients. Plugins that report that they support `ReadLogs` must implement the |
| `/LogDriver.ReadLogs` endpoint |
| |
| ### `/LogDriver.ReadLogs` |
| |
| Reads back logs to the client. This is used when `docker logs <container>` is |
| called. |
| |
| In order for Docker to use this endpoint, the plugin must specify as much when |
| `/LogDriver.Capabilities` is called. |
| |
| Request: |
| |
| ```json |
| { |
| "ReadConfig": {}, |
| "Info": { |
| "ContainerID": "123456" |
| } |
| } |
| ``` |
| |
| `ReadConfig` is the list of options for reading, it is defined with the following |
| golang struct: |
| |
| ```go |
| type ReadConfig struct { |
| Since time.Time |
| Tail int |
| Follow bool |
| } |
| ``` |
| |
| - `Since` defines the oldest log that should be sent. |
| - `Tail` defines the number of lines to read (e.g. like the command `tail -n 10`) |
| - `Follow` signals that the client wants to stay attached to receive new log messages |
| as they come in once the existing logs have been read. |
| |
| `Info` is the same type defined in `/LogDriver.StartLogging`. It should be used |
| to determine what set of logs to read. |
| |
| Response: |
| |
| ```text |
| {{ log stream }} |
| ``` |
| |
| The response should be the encoded log message using the same format as the |
| messages that the plugin consumed from Docker. |