2016-10-14 18:30:36 -04:00
---
2024-01-10 04:38:42 -05:00
title: Docker Engine managed plugin system
2016-10-20 14:12:02 -04:00
description: Develop and use a plugin with the managed plugin system
2016-11-03 17:21:33 -04:00
keywords: "API, Usage, plugins, documentation, developer"
2024-06-18 10:41:55 -04:00
aliases:
- "/engine/extend/plugins_graphdriver/"
2016-10-14 18:30:36 -04:00
---
2016-10-12 19:23:01 -04:00
2022-10-14 14:44:16 -04:00
- [Installing and using a plugin ](index.md#installing-and-using-a-plugin )
- [Developing a plugin ](index.md#developing-a-plugin )
- [Debugging plugins ](index.md#debugging-plugins )
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
Docker Engine's plugin system lets you install, start, stop, and remove
2017-02-14 19:40:15 -05:00
plugins using Docker Engine.
2016-10-12 19:23:01 -04:00
2020-10-26 13:30:01 -04:00
For information about legacy (non-managed) plugins, refer to
[Understand legacy Docker Engine plugins ](legacy_plugins.md ).
2016-10-12 19:23:01 -04:00
2020-04-19 11:09:14 -04:00
> **Note**
>
> Docker Engine managed plugins are currently not supported on Windows daemons.
2016-11-22 10:01:14 -05:00
2016-10-20 14:12:02 -04:00
## Installing and using a plugin
2016-10-12 19:23:01 -04:00
2016-10-20 14:12:02 -04:00
Plugins are distributed as Docker images and can be hosted on Docker Hub or on
a private registry.
2016-10-12 19:23:01 -04:00
2016-10-20 14:12:02 -04:00
To install a plugin, use the `docker plugin install` command, which pulls the
2017-02-21 05:38:07 -05:00
plugin from Docker Hub or your private registry, prompts you to grant
2016-10-20 14:12:02 -04:00
permissions or capabilities if necessary, and enables the plugin.
2016-10-12 19:23:01 -04:00
2016-10-20 14:12:02 -04:00
To check the status of installed plugins, use the `docker plugin ls` command.
Plugins that start successfully are listed as enabled in the output.
2016-10-12 19:23:01 -04:00
2016-10-20 14:12:02 -04:00
After a plugin is installed, you can use it as an option for another Docker
operation, such as creating a volume.
2016-10-12 19:23:01 -04:00
2017-09-06 18:36:20 -04:00
In the following example, you install the `sshfs` plugin, verify that it is
2016-10-20 14:12:02 -04:00
enabled, and use it to create a volume.
2016-10-12 19:23:01 -04:00
2020-04-19 11:09:14 -04:00
> **Note**
>
> This example is intended for instructional purposes only. Once the volume is
2024-01-10 04:38:42 -05:00
> created, your SSH password to the remote host is exposed as plaintext when
> inspecting the volume. Delete the volume as soon as you are done with the
> example.
2017-09-06 18:36:20 -04:00
2024-01-10 04:38:42 -05:00
1. Install the `sshfs` plugin.
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
```console
$ docker plugin install vieux/sshfs
2017-09-06 18:36:20 -04:00
2024-01-10 04:38:42 -05:00
Plugin "vieux/sshfs" is requesting the following privileges:
- network: [host]
- capabilities: [CAP_SYS_ADMIN]
Do you grant the above permissions? [y/N] y
2017-09-06 18:36:20 -04:00
2024-01-10 04:38:42 -05:00
vieux/sshfs
```
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
The plugin requests 2 privileges:
2017-10-13 17:59:19 -04:00
2024-01-10 04:38:42 -05:00
- It needs access to the `host` network.
- It needs the `CAP_SYS_ADMIN` capability, which allows the plugin to run
the `mount` command.
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
2. Check that the plugin is enabled in the output of `docker plugin ls` .
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
```console
$ docker plugin ls
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
ID NAME TAG DESCRIPTION ENABLED
69553ca1d789 vieux/sshfs latest the `sshfs` plugin true
```
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
3. Create a volume using the plugin.
This example mounts the `/remote` directory on host `1.2.3.4` into a
volume named `sshvolume` .
2017-02-14 19:40:15 -05:00
2024-01-10 04:38:42 -05:00
This volume can now be mounted into containers.
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
```console
$ docker volume create \
-d vieux/sshfs \
--name sshvolume \
-o sshcmd=user@1.2.3.4:/remote \
-o password=$(cat file_containing_password_for_remote_host)
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
sshvolume
```
2021-08-21 08:54:14 -04:00
2024-01-10 04:38:42 -05:00
4. Verify that the volume was created successfully.
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
```console
$ docker volume ls
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
DRIVER NAME
vieux/sshfs sshvolume
```
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
5. Start a container that uses the volume `sshvolume` .
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
```console
$ docker run --rm -v sshvolume:/data busybox ls /data
2017-09-06 18:36:20 -04:00
2024-01-10 04:38:42 -05:00
< content of / remote on machine 1 . 2 . 3 . 4 >
```
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
6. Remove the volume `sshvolume`
2022-10-14 14:44:16 -04:00
2024-01-10 04:38:42 -05:00
```console
$ docker volume rm sshvolume
2017-02-14 19:40:15 -05:00
2024-01-10 04:38:42 -05:00
sshvolume
```
2021-08-21 08:54:14 -04:00
2016-10-20 14:12:02 -04:00
To disable a plugin, use the `docker plugin disable` command. To completely
remove it, use the `docker plugin remove` command. For other available
commands and options, see the
2024-04-12 05:10:58 -04:00
[command line reference ](https://docs.docker.com/reference/cli/docker/ ).
2016-10-12 19:23:01 -04:00
2016-10-20 14:12:02 -04:00
## Developing a plugin
2016-10-12 19:23:01 -04:00
2016-10-20 14:12:02 -04:00
#### The rootfs directory
2022-10-14 14:44:16 -04:00
2016-10-20 14:12:02 -04:00
The `rootfs` directory represents the root filesystem of the plugin. In this
example, it was created from a Dockerfile:
2016-10-12 19:23:01 -04:00
2024-01-10 04:38:42 -05:00
> **Note**
>
> The `/run/docker/plugins` directory is mandatory inside of the
> plugin's filesystem for Docker to communicate with the plugin.
2016-10-12 19:23:01 -04:00
2021-08-21 08:54:14 -04:00
```console
2016-10-12 19:23:01 -04:00
$ git clone https://github.com/vieux/docker-volume-sshfs
$ cd docker-volume-sshfs
2016-12-12 18:05:53 -05:00
$ docker build -t rootfsimage .
$ id=$(docker create rootfsimage true) # id was cd851ce43a403 when the image was created
$ sudo mkdir -p myplugin/rootfs
$ sudo docker export "$id" | sudo tar -x -C myplugin/rootfs
2016-10-12 19:23:01 -04:00
$ docker rm -vf "$id"
2016-12-12 18:05:53 -05:00
$ docker rmi rootfsimage
2016-10-12 19:23:01 -04:00
```
2016-12-12 18:05:53 -05:00
#### The config.json file
2016-10-12 19:23:01 -04:00
2016-12-12 18:05:53 -05:00
The `config.json` file describes the plugin. See the [plugins config reference ](config.md ).
2016-10-20 14:12:02 -04:00
2016-11-07 21:51:47 -05:00
Consider the following `config.json` file.
2016-10-20 14:12:02 -04:00
```json
2016-10-12 19:23:01 -04:00
{
2022-10-14 14:44:16 -04:00
"description": "sshFS plugin for Docker",
"documentation": "https://docs.docker.com/engine/extend/plugins/",
"entrypoint": ["/docker-volume-sshfs"],
"network": {
"type": "host"
},
"interface": {
"types": ["docker.volumedriver/1.0"],
"socket": "sshfs.sock"
},
"linux": {
"capabilities": ["CAP_SYS_ADMIN"]
}
2016-10-12 19:23:01 -04:00
}
```
2016-10-20 14:12:02 -04:00
This plugin is a volume driver. It requires a `host` network and the
2017-03-07 04:06:27 -05:00
`CAP_SYS_ADMIN` capability. It depends upon the `/docker-volume-sshfs`
2016-10-20 14:12:02 -04:00
entrypoint and uses the `/run/docker/plugins/sshfs.sock` socket to communicate
2016-12-12 18:05:53 -05:00
with Docker Engine. This plugin has no runtime parameters.
2016-10-20 14:12:02 -04:00
2017-01-19 15:25:16 -05:00
#### Creating the plugin
2016-10-20 14:12:02 -04:00
2016-12-12 18:05:53 -05:00
A new plugin can be created by running
`docker plugin create <plugin-name> ./path/to/plugin/data` where the plugin
data contains a plugin configuration file `config.json` and a root filesystem
2017-02-14 19:40:15 -05:00
in subdirectory `rootfs` .
2016-10-20 14:12:02 -04:00
2016-12-12 18:05:53 -05:00
After that the plugin `<plugin-name>` will show up in `docker plugin ls` .
Plugins can be pushed to remote registries with
2017-01-19 15:25:16 -05:00
`docker plugin push <plugin-name>` .
2017-02-06 17:44:56 -05:00
## Debugging plugins
Stdout of a plugin is redirected to dockerd logs. Such entries have a
`plugin=<ID>` suffix. Here are a few examples of commands for pluginID
`f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62` and their
corresponding log entries in the docker daemon logs.
2021-08-21 08:54:14 -04:00
```console
2017-08-07 05:04:05 -04:00
$ docker plugin install tiborvass/sample-volume-plugin
2017-02-06 17:44:56 -05:00
INFO[0036] Starting... Found 0 volumes on startup plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
```
2021-08-21 08:54:14 -04:00
```console
2017-08-07 05:04:05 -04:00
$ docker volume create -d tiborvass/sample-volume-plugin samplevol
2017-02-06 17:44:56 -05:00
INFO[0193] Create Called... Ensuring directory /data/samplevol exists on host... plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
INFO[0193] open /var/lib/docker/plugin-data/local-persist.json: no such file or directory plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
INFO[0193] Created volume samplevol with mountpoint /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
INFO[0193] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
```
2021-08-21 08:54:14 -04:00
```console
2017-02-06 17:44:56 -05:00
$ docker run -v samplevol:/tmp busybox sh
INFO[0421] Get Called... Found samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
INFO[0421] Mount Called... Mounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
INFO[0421] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
INFO[0421] Unmount Called... Unmounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
```
2024-01-10 04:38:42 -05:00
#### Using runc to obtain logfiles and shell into the plugin.
2017-02-06 17:44:56 -05:00
2024-01-10 04:38:42 -05:00
Use `runc` , the default docker container runtime, for debugging plugins by
collecting plugin logs redirected to a file.
2017-02-06 17:44:56 -05:00
2021-08-21 08:54:14 -04:00
```console
2022-10-14 14:44:16 -04:00
$ sudo runc --root /run/docker/runtime-runc/plugins.moby list
2018-04-05 15:14:59 -04:00
ID PID STATUS BUNDLE CREATED OWNER
93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 15806 running /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins/93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 2018-02-08T21:40:08.621358213Z root
9b4606d84e06b56df84fadf054a21374b247941c94ce405b0a261499d689d9c9 14992 running /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins/9b4606d84e06b56df84fadf054a21374b247941c94ce405b0a261499d689d9c9 2018-02-08T21:35:12.321325872Z root
c5bb4b90941efcaccca999439ed06d6a6affdde7081bb34dc84126b57b3e793d 14984 running /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins/c5bb4b90941efcaccca999439ed06d6a6affdde7081bb34dc84126b57b3e793d 2018-02-08T21:35:12.321288966Z root
2017-02-06 17:44:56 -05:00
```
2021-08-21 08:54:14 -04:00
```console
2022-10-14 14:44:16 -04:00
$ sudo runc --root /run/docker/runtime-runc/plugins.moby exec 93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 cat /var/log/plugin.log
2017-02-06 17:44:56 -05:00
```
If the plugin has a built-in shell, then exec into the plugin can be done as
follows:
2021-08-21 08:54:14 -04:00
```console
2022-10-14 14:44:16 -04:00
$ sudo runc --root /run/docker/runtime-runc/plugins.moby exec -t 93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 sh
2017-02-06 17:44:56 -05:00
```
2017-02-10 17:08:36 -05:00
#### Using curl to debug plugin socket issues.
To verify if the plugin API socket that the docker daemon communicates with
2017-02-14 19:40:15 -05:00
is responsive, use curl. In this example, we will make API calls from the
2017-02-10 17:08:36 -05:00
docker host to volume and network plugins using curl 7.47.0 to ensure that
the plugin is listening on the said socket. For a well functioning plugin,
these basic requests should work. Note that plugin sockets are available on the host under `/var/run/docker/plugins/<pluginID>`
2021-08-21 08:54:14 -04:00
```console
$ curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/e8a37ba56fc879c991f7d7921901723c64df6b42b87e6a0b055771ecf8477a6d/plugin.sock http:/VolumeDriver.List
2017-02-10 17:08:36 -05:00
{"Mountpoint":"","Err":"","Volumes":[{"Name":"myvol1","Mountpoint":"/data/myvol1"},{"Name":"myvol2","Mountpoint":"/data/myvol2"}],"Volume":null}
```
2021-08-21 08:54:14 -04:00
```console
$ curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/45e00a7ce6185d6e365904c8bcf62eb724b1fe307e0d4e7ecc9f6c1eb7bcdb70/plugin.sock http:/NetworkDriver.GetCapabilities
2017-02-10 17:08:36 -05:00
{"Scope":"local"}
```
2021-08-21 08:54:14 -04:00
2017-02-14 19:40:15 -05:00
When using curl 7.5 and above, the URL should be of the form
`http://hostname/APICall` , where `hostname` is the valid hostname where the
2017-02-10 17:08:36 -05:00
plugin is installed and `APICall` is the call to the plugin API.
For example, `http://localhost/VolumeDriver.List`