Overview
Add a DockerModel provider to plugin-ai that routes inference requests to a locally running Docker Model Runner instance.
Docker Model Runner (docs) exposes an OpenAI-compatible REST API at http://localhost:12434/engines/v1, requiring no authentication. This means DockerModel can extend the existing OpenAICompliantProvider base class and re-use the full provider infrastructure with minimal new code.
Motivation
Docker Model Runner is now a first-class Docker feature available out-of-the-box on Docker Desktop and Docker Engine (Linux). For Kestra users who run local or on-prem workflows, it provides a zero-friction path to self-hosted LLM inference without managing a separate Ollama or LocalAI stack. Adding a dedicated provider makes the integration explicit and discoverable.
Link with plugin-docker
plugin-docker (kestra-io/plugin-docker#119) adds dedicated tasks (docker.model.Pull, docker.model.List, etc.) to manage the Docker Model Runner model lifecycle from a Kestra flow.
The separation of concerns is intentional: plugin-docker owns model lifecycle (pull, configure, delete), plugin-ai owns inference. A typical flow chains both:
tasks:
- id: pull_model
type: io.kestra.plugin.docker.model.Pull
model: ai/smollm2
- id: ask
type: io.kestra.plugin.ai.completion.ChatCompletion
provider:
type: io.kestra.plugin.ai.provider.DockerModel
modelName: ai/smollm2
messages:
- role: user
content: What is Docker Model Runner?
Implementation
New class: io.kestra.plugin.ai.provider.DockerModel
Extends OpenAICompliantProvider (same parent as OpenAI, AzureOpenAI).
Properties:
| Property |
Type |
Default |
Notes |
modelName |
Property<String> |
required |
e.g. ai/smollm2, ai/llama3.2:3b-instruct-q4_k_m, hf.co/bartowski/Llama-3.2-1B-Instruct-GGUF |
baseUrl |
Property<String> |
http://localhost:12434/engines/v1 |
Override for Docker Engine remote (e.g. http://172.17.0.1:12434/engines/v1) |
apiKey |
Property<String> |
"not-needed" (default) |
Accepted but ignored by DMR; required by OpenAI SDK |
Supported capabilities:
chatModel() — chat completions (/engines/v1/chat/completions)
embeddingModel() — text embeddings (/engines/v1/embeddings)
imageModel() — image generation via Diffusers (/engines/diffusers/v1/images/generations, requires a diffuser-tagged model such as ai/stable-diffusion)
Behaviour notes:
- No API key is required by Docker Model Runner; the
apiKey field should default to "not-needed" and be marked optional in the schema
- Base URL for containers should be
http://model-runner.docker.internal/engines/v1 (Docker Desktop) or http://172.17.0.1:12434/engines/v1 (Docker Engine)
- The
baseUrl field should be prominently documented with both variants
Acceptance Criteria
References
- Docker Model Runner docs
- OpenAI-compatible base URL:
http://localhost:12434/engines/v1
- Anthropic-compatible base URL:
http://localhost:12434/anthropic
- Ollama-compatible base URL:
http://localhost:12434
- Supported model list:
ai/* namespace on Docker Hub (74+ repos)
- Existing similar provider for reference:
io.kestra.plugin.ai.provider.Ollama, io.kestra.plugin.ai.provider.LocalAI
- Companion issue: kestra-io/plugin-docker#119 — model lifecycle management tasks
Overview
Add a
DockerModelprovider toplugin-aithat routes inference requests to a locally running Docker Model Runner instance.Docker Model Runner (docs) exposes an OpenAI-compatible REST API at
http://localhost:12434/engines/v1, requiring no authentication. This meansDockerModelcan extend the existingOpenAICompliantProviderbase class and re-use the full provider infrastructure with minimal new code.Motivation
Docker Model Runner is now a first-class Docker feature available out-of-the-box on Docker Desktop and Docker Engine (Linux). For Kestra users who run local or on-prem workflows, it provides a zero-friction path to self-hosted LLM inference without managing a separate Ollama or LocalAI stack. Adding a dedicated provider makes the integration explicit and discoverable.
Link with plugin-docker
plugin-docker(kestra-io/plugin-docker#119) adds dedicated tasks (docker.model.Pull,docker.model.List, etc.) to manage the Docker Model Runner model lifecycle from a Kestra flow.The separation of concerns is intentional: plugin-docker owns model lifecycle (pull, configure, delete), plugin-ai owns inference. A typical flow chains both:
Implementation
New class:
io.kestra.plugin.ai.provider.DockerModelExtends
OpenAICompliantProvider(same parent asOpenAI,AzureOpenAI).Properties:
modelNameProperty<String>ai/smollm2,ai/llama3.2:3b-instruct-q4_k_m,hf.co/bartowski/Llama-3.2-1B-Instruct-GGUFbaseUrlProperty<String>http://localhost:12434/engines/v1http://172.17.0.1:12434/engines/v1)apiKeyProperty<String>"not-needed"(default)Supported capabilities:
chatModel()— chat completions (/engines/v1/chat/completions)embeddingModel()— text embeddings (/engines/v1/embeddings)imageModel()— image generation via Diffusers (/engines/diffusers/v1/images/generations, requires adiffuser-tagged model such asai/stable-diffusion)Behaviour notes:
apiKeyfield should default to"not-needed"and be marked optional in the schemahttp://model-runner.docker.internal/engines/v1(Docker Desktop) orhttp://172.17.0.1:12434/engines/v1(Docker Engine)baseUrlfield should be prominently documented with both variantsAcceptance Criteria
DockerModelprovider implemented extendingOpenAICompliantProviderbaseUrldefaults tohttp://localhost:12434/engines/v1; clearly documented with container-internal variantsapiKeyis optional, defaults to"not-needed"chatModel(),embeddingModel(), andimageModel()implemented (image generation routes to/engines/diffusers/v1/)@Schema,@Plugin, and@Exampleannotations with at least one working flow example@DockerModelRunnerTest(skippable when DMR is unavailable)References
http://localhost:12434/engines/v1http://localhost:12434/anthropichttp://localhost:12434ai/*namespace on Docker Hub (74+ repos)io.kestra.plugin.ai.provider.Ollama,io.kestra.plugin.ai.provider.LocalAI