Плагины драйверов журнала Docker

В этом документе определяются подключаемые модули драйверов ведения журналов для Docker.

Драйверы ведения журналов позволяют пользователям пересылать журналы контейнеров в другую службу для обработки. Docker включает в себя несколько встроенных драйверов ведения журналов, однако никогда не может рассчитывать на поддержку всех вариантов использования со встроенными драйверами. Плагины позволяют Docker поддерживать широкий спектр служб ведения журналов, не требуя встраивания клиентских библиотек для данных служб в основную кодовую базу Docker. См. документация к плагину для получения дополнительной информации.

Создаёт плагин ведения журнала

Основной интерфейс для подключаемых модулей ведения журнала использует тот же протокол JSON+HTTP RPC, что и другие типы подключаемых модулей. См. подключаемый модуль пример для эталонной реализации подключаемого модуля ведения журнала. В примере используется встроенный драйвер журнала jsonfilelog.

Протокол LogDriver

Плагины ведения журнала должны регистрироваться как LogDriver во время активации плагина. После активации пользователи могут указывает плагин в качестве драйвера журнала.

Есть две конечные точки HTTP, которые должны реализовать подключаемые модули ведения журнала:

/LogDriver.StartLogging

Сигналы подключаемому модулю о запуске контейнера, для которого подключаемый модуль должен начать получать журналы.

Журналы будут передаваться через файл, указанный в запросе. В Linux данный файл представляет собой FIFO. Плагины ведения журналов в настоящее время не поддерживаются в Windows.

Запрос:

{
             "File": "/path/to/file/stream",
             "Info": {
                     "ContainerID": "123456"
             }
}

File — это путь к потоку журнала, который необходимо использовать. Каждый вызов StartLogging должен предоставлять другой путь к файлу, даже если это контейнер, для которого подключаемый модуль уже получил журналы ранее. Файл создаётся докером со случайно сгенерированным именем.

Info — это сведения о регистрируемом контейнере. Это довольно свободная форма, но определяется следующим определением структуры:

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 всегда будет поставляться с этой структурой, но другие поля могут быть пустыми или отсутствовать.

Ответ

{
     "Err": ""
}

Если во время этого запроса произошла ошибка, добавляет сообщение об ошибке в поле Err ответа. Если ошибки нет, вы можете либо отправить пустой ответ ({}), либо пустое значение для поля Err.

В данный момент драйвер должен использовать сообщения журнала из переданного файла. Если сообщения не используются, это может привести к блокировке контейнера при попытке записи в его потоки stdio.

Сообщения потока журнала кодируются как буферы протокола. Определения protobuf находятся в репозиторий докеров.

Поскольку буферы протоколов не являются самоограниченными, вы должны декодировать их из потока, используя следующий формат потока:

[size][message]

Где size — это 4-байтовый двоичный код с обратным порядком байтов, закодированный uint32. size в данном случае определяет размер следующего сообщения. message — это фактическая запись в журнале.

Справочную реализацию кодировщика/декодера потока в golang можно найти по адресу здесь

/LogDriver.StopLogging

Сигнализирует подключаемому модулю прекратить сбор журналов из указанного файла. После получения ответа файл будет удален Docker. Вы должны убедиться, что собрали все журналы в потоке, прежде чем отвечать на данный запрос, иначе вы рискуете потерять данные журнала.

Запросы на эту конечную точку не означают, что контейнер был удален, а только то, что он остановлен.

Запрос:

{
             "File": "/path/to/file/stream"
}

Ответ:

{
     "Err": ""
}

Если во время этого запроса произошла ошибка, добавляет сообщение об ошибке в поле Err ответа. Если ошибки нет, вы можете либо отправить пустой ответ ({}), либо пустое значение для поля Err.

Необязательные конечные точки

Плагины ведения журнала могут реализовывать две дополнительные конечные точки ведения журнала:

/LogDriver.Capabilities

Определяет возможности драйвера журнала. Вы должны реализовать эту конечную точку, чтобы Docker мог использовать преимущества любой из определённых возможностей.

Запрос:

{}

Ответ:

{
     "ReadLogs": true
}

Поддерживаемые возможности:

  • ReadLogs — сообщает Docker, что плагин может считывать журналы для клиентов. Плагины, сообщающие о поддержке ReadLogs, должны реализовывать конечную точку /LogDriver.ReadLogs

/LogDriver.ReadLogs

Читает журналы обратно клиенту. Это используется при вызове docker logs <container>.

Чтобы Docker мог использовать эту конечную точку, плагин должен указывает её при вызове /LogDriver.Capabilities.

Запрос:

{
     "ReadConfig": {},
     "Info": {
             "ContainerID": "123456"
     }
}

ReadConfig — это список опций для чтения, он определяется следующей структурой golang:

type ReadConfig struct {
     Since  time.Time
     Tail   int
     Follow bool
}
  • Since определяет самый старый журнал, который должен быть отправлен.

  • Tail определяет количество строк для чтения (например, как команда tail -n 10)

  • Follow сигнализирует о том, что клиент хочет оставаться подключенным для получения новых сообщений журнала по мере их поступления после прочтения существующих журналов.

Info — это тот же тип, что и в /LogDriver.StartLogging. Его следует использовать для определения того, какой множество журналов читать.

Ответ:

{{ log stream }}

Ответ должен представлять собой закодированное сообщение журнала, использующее тот же формат, что и сообщения, которые подключаемый модуль получает от Docker.