1---
2title: Docker Engine managed plugin system
3description: Develop and use a plugin with the managed plugin system
4keywords: "API, Usage, plugins, documentation, developer"
5---
6
7- [Installing and using a plugin](index.md#installing-and-using-a-plugin)
8- [Developing a plugin](index.md#developing-a-plugin)
9- [Debugging plugins](index.md#debugging-plugins)
10
11Docker Engine's plugin system lets you install, start, stop, and remove
12plugins using Docker Engine.
13
14For information about legacy (non-managed) plugins, refer to
15[Understand legacy Docker Engine plugins](legacy_plugins.md).
16
17> **Note**
18>
19> Docker Engine managed plugins are currently not supported on Windows daemons.
20
21## Installing and using a plugin
22
23Plugins are distributed as Docker images and can be hosted on Docker Hub or on
24a private registry.
25
26To install a plugin, use the `docker plugin install` command, which pulls the
27plugin from Docker Hub or your private registry, prompts you to grant
28permissions or capabilities if necessary, and enables the plugin.
29
30To check the status of installed plugins, use the `docker plugin ls` command.
31Plugins that start successfully are listed as enabled in the output.
32
33After a plugin is installed, you can use it as an option for another Docker
34operation, such as creating a volume.
35
36In the following example, you install the `sshfs` plugin, verify that it is
37enabled, and use it to create a volume.
38
39> **Note**
40>
41> This example is intended for instructional purposes only. Once the volume is
42> created, your SSH password to the remote host is exposed as plaintext when
43> inspecting the volume. Delete the volume as soon as you are done with the
44> example.
45
461. Install the `sshfs` plugin.
47
48 ```console
49 $ docker plugin install vieux/sshfs
50
51 Plugin "vieux/sshfs" is requesting the following privileges:
52 - network: [host]
53 - capabilities: [CAP_SYS_ADMIN]
54 Do you grant the above permissions? [y/N] y
55
56 vieux/sshfs
57 ```
58
59 The plugin requests 2 privileges:
60
61 - It needs access to the `host` network.
62 - It needs the `CAP_SYS_ADMIN` capability, which allows the plugin to run
63 the `mount` command.
64
652. Check that the plugin is enabled in the output of `docker plugin ls`.
66
67 ```console
68 $ docker plugin ls
69
70 ID NAME TAG DESCRIPTION ENABLED
71 69553ca1d789 vieux/sshfs latest the `sshfs` plugin true
72 ```
73
743. Create a volume using the plugin.
75 This example mounts the `/remote` directory on host `1.2.3.4` into a
76 volume named `sshvolume`.
77
78 This volume can now be mounted into containers.
79
80 ```console
81 $ docker volume create \
82 -d vieux/sshfs \
83 --name sshvolume \
84 -o sshcmd=user@1.2.3.4:/remote \
85 -o password=$(cat file_containing_password_for_remote_host)
86
87 sshvolume
88 ```
89
904. Verify that the volume was created successfully.
91
92 ```console
93 $ docker volume ls
94
95 DRIVER NAME
96 vieux/sshfs sshvolume
97 ```
98
995. Start a container that uses the volume `sshvolume`.
100
101 ```console
102 $ docker run --rm -v sshvolume:/data busybox ls /data
103
104 <content of /remote on machine 1.2.3.4>
105 ```
106
1076. Remove the volume `sshvolume`
108
109 ```console
110 $ docker volume rm sshvolume
111
112 sshvolume
113 ```
114
115To disable a plugin, use the `docker plugin disable` command. To completely
116remove it, use the `docker plugin remove` command. For other available
117commands and options, see the
118[command line reference](https://docs.docker.com/engine/reference/commandline/cli/).
119
120## Developing a plugin
121
122#### The rootfs directory
123
124The `rootfs` directory represents the root filesystem of the plugin. In this
125example, it was created from a Dockerfile:
126
127> **Note**
128>
129> The `/run/docker/plugins` directory is mandatory inside of the
130> plugin's filesystem for Docker to communicate with the plugin.
131
132```console
133$ git clone https://github.com/vieux/docker-volume-sshfs
134$ cd docker-volume-sshfs
135$ docker build -t rootfsimage .
136$ id=$(docker create rootfsimage true) # id was cd851ce43a403 when the image was created
137$ sudo mkdir -p myplugin/rootfs
138$ sudo docker export "$id" | sudo tar -x -C myplugin/rootfs
139$ docker rm -vf "$id"
140$ docker rmi rootfsimage
141```
142
143#### The config.json file
144
145The `config.json` file describes the plugin. See the [plugins config reference](config.md).
146
147Consider the following `config.json` file.
148
149```json
150{
151 "description": "sshFS plugin for Docker",
152 "documentation": "https://docs.docker.com/engine/extend/plugins/",
153 "entrypoint": ["/docker-volume-sshfs"],
154 "network": {
155 "type": "host"
156 },
157 "interface": {
158 "types": ["docker.volumedriver/1.0"],
159 "socket": "sshfs.sock"
160 },
161 "linux": {
162 "capabilities": ["CAP_SYS_ADMIN"]
163 }
164}
165```
166
167This plugin is a volume driver. It requires a `host` network and the
168`CAP_SYS_ADMIN` capability. It depends upon the `/docker-volume-sshfs`
169entrypoint and uses the `/run/docker/plugins/sshfs.sock` socket to communicate
170with Docker Engine. This plugin has no runtime parameters.
171
172#### Creating the plugin
173
174A new plugin can be created by running
175`docker plugin create <plugin-name> ./path/to/plugin/data` where the plugin
176data contains a plugin configuration file `config.json` and a root filesystem
177in subdirectory `rootfs`.
178
179After that the plugin `<plugin-name>` will show up in `docker plugin ls`.
180Plugins can be pushed to remote registries with
181`docker plugin push <plugin-name>`.
182
183## Debugging plugins
184
185Stdout of a plugin is redirected to dockerd logs. Such entries have a
186`plugin=<ID>` suffix. Here are a few examples of commands for pluginID
187`f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62` and their
188corresponding log entries in the docker daemon logs.
189
190```console
191$ docker plugin install tiborvass/sample-volume-plugin
192
193INFO[0036] Starting... Found 0 volumes on startup plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
194```
195
196```console
197$ docker volume create -d tiborvass/sample-volume-plugin samplevol
198
199INFO[0193] Create Called... Ensuring directory /data/samplevol exists on host... plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
200INFO[0193] open /var/lib/docker/plugin-data/local-persist.json: no such file or directory plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
201INFO[0193] Created volume samplevol with mountpoint /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
202INFO[0193] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
203```
204
205```console
206$ docker run -v samplevol:/tmp busybox sh
207
208INFO[0421] Get Called... Found samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
209INFO[0421] Mount Called... Mounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
210INFO[0421] Path Called... Returned path /data/samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
211INFO[0421] Unmount Called... Unmounted samplevol plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
212```
213
214#### Using runc to obtain logfiles and shell into the plugin.
215
216Use `runc`, the default docker container runtime, for debugging plugins by
217collecting plugin logs redirected to a file.
218
219```console
220$ sudo runc --root /run/docker/runtime-runc/plugins.moby list
221
222ID PID STATUS BUNDLE CREATED OWNER
22393f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 15806 running /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins/93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 2018-02-08T21:40:08.621358213Z root
2249b4606d84e06b56df84fadf054a21374b247941c94ce405b0a261499d689d9c9 14992 running /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins/9b4606d84e06b56df84fadf054a21374b247941c94ce405b0a261499d689d9c9 2018-02-08T21:35:12.321325872Z root
225c5bb4b90941efcaccca999439ed06d6a6affdde7081bb34dc84126b57b3e793d 14984 running /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins/c5bb4b90941efcaccca999439ed06d6a6affdde7081bb34dc84126b57b3e793d 2018-02-08T21:35:12.321288966Z root
226```
227
228```console
229$ sudo runc --root /run/docker/runtime-runc/plugins.moby exec 93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 cat /var/log/plugin.log
230```
231
232If the plugin has a built-in shell, then exec into the plugin can be done as
233follows:
234
235```console
236$ sudo runc --root /run/docker/runtime-runc/plugins.moby exec -t 93f1e7dbfe11c938782c2993628c895cf28e2274072c4a346a6002446c949b25 sh
237```
238
239#### Using curl to debug plugin socket issues.
240
241To verify if the plugin API socket that the docker daemon communicates with
242is responsive, use curl. In this example, we will make API calls from the
243docker host to volume and network plugins using curl 7.47.0 to ensure that
244the plugin is listening on the said socket. For a well functioning plugin,
245these basic requests should work. Note that plugin sockets are available on the host under `/var/run/docker/plugins/<pluginID>`
246
247```console
248$ curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/e8a37ba56fc879c991f7d7921901723c64df6b42b87e6a0b055771ecf8477a6d/plugin.sock http:/VolumeDriver.List
249
250{"Mountpoint":"","Err":"","Volumes":[{"Name":"myvol1","Mountpoint":"/data/myvol1"},{"Name":"myvol2","Mountpoint":"/data/myvol2"}],"Volume":null}
251```
252
253```console
254$ curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/45e00a7ce6185d6e365904c8bcf62eb724b1fe307e0d4e7ecc9f6c1eb7bcdb70/plugin.sock http:/NetworkDriver.GetCapabilities
255
256{"Scope":"local"}
257```
258
259When using curl 7.5 and above, the URL should be of the form
260`http://hostname/APICall`, where `hostname` is the valid hostname where the
261plugin is installed and `APICall` is the call to the plugin API.
262
263For example, `http://localhost/VolumeDriver.List`
View as plain text