mirror of https://github.com/docker/cli.git
274 lines
10 KiB
Markdown
274 lines
10 KiB
Markdown
---
|
||
description: Develop and use a plugin with the managed plugin system
|
||
keywords: "API, Usage, plugins, documentation, developer"
|
||
title: Managed plugin system
|
||
---
|
||
|
||
<!-- This file is maintained within the docker/cli Github
|
||
repository at https://github.com/docker/cli/. Make all
|
||
pull requests against that repo. If you see this file in
|
||
another repository, consider it read-only there, as it will
|
||
periodically be overwritten by the definitive file. Pull
|
||
requests which include edits to this file in other repositories
|
||
will be rejected.
|
||
-->
|
||
|
||
# Docker Engine managed plugin system
|
||
|
||
* [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)
|
||
|
||
Docker Engine's plugin system allows you to install, start, stop, and remove
|
||
plugins using Docker Engine.
|
||
|
||
For information about the legacy plugin system available in Docker Engine 1.12
|
||
and earlier, see [Understand legacy Docker Engine plugins](legacy_plugins.md).
|
||
|
||
> **Note**: Docker Engine managed plugins are currently not supported
|
||
on Windows daemons.
|
||
|
||
## Installing and using a plugin
|
||
|
||
Plugins are distributed as Docker images and can be hosted on Docker Hub or on
|
||
a private registry.
|
||
|
||
To install a plugin, use the `docker plugin install` command, which pulls the
|
||
plugin from Docker Hub or your private registry, prompts you to grant
|
||
permissions or capabilities if necessary, and enables the plugin.
|
||
|
||
To check the status of installed plugins, use the `docker plugin ls` command.
|
||
Plugins that start successfully are listed as enabled in the output.
|
||
|
||
After a plugin is installed, you can use it as an option for another Docker
|
||
operation, such as creating a volume.
|
||
|
||
In the following example, you install the `docker4x/cloudstor` plugin, verify that it is
|
||
enabled, and use it to create a volume.
|
||
|
||
1. Install the `sshfs` plugin.
|
||
|
||
```bash
|
||
$ docker plugin install docker4x/cloudstor:17.05.0-ce-azure2 \
|
||
--alias cloudstor:azure \
|
||
CLOUD_PLATFORM=AZURE \
|
||
AZURE_STORAGE_ACCOUNT_KEY="mmpwuGgnSKHodND...." \
|
||
AZURE_STORAGE_ACCOUNT="myswarmstorage"
|
||
|
||
Plugin "docker4x/cloudstor:17.06.0-ce-azure2" is requesting the following privileges:
|
||
- network: [host]
|
||
- mount: [/dev]
|
||
- allow-all-devices: [true]
|
||
services:
|
||
- capabilities: [CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH]
|
||
Do you grant the above permissions? [y/N] y
|
||
17.06.0-ce-azure2: Pulling from docker4x/cloudstor
|
||
68b66459b745: Verifying Checksum
|
||
68b66459b745: Download complete
|
||
Digest: sha256:aa2ae6026e8f5c84d3992e239ec7eec2c578090f10528a51bd8c311d5da48c7a
|
||
Status: Downloaded newer image for docker4x/cloudstor:17.05.0-ce-azure2
|
||
Installed plugin docker4x/cloudstor:17.06.0-ce-azure2
|
||
```
|
||
|
||
The plugin requests 4 privileges:
|
||
|
||
- It needs access to the `host` network.
|
||
- It needs access to the `/dev` mount.
|
||
- It needs access to `allow-all-devices`.
|
||
- It needs the `CAP_SYS_ADMIN` capability, which allows the plugin to run
|
||
the `mount` command.
|
||
- It needs the `CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH`capabilities, which allows the plugin to bypass file read, write, and execute permission checks.
|
||
|
||
2. Check that the plugin is enabled in the output of `docker plugin ls`.
|
||
|
||
```bash
|
||
$ docker plugin ls
|
||
|
||
ID NAME DESCRIPTION ENABLED
|
||
7e08f3d484c9 cloudstor:azure cloud storage plugin for Docker true
|
||
```
|
||
|
||
3. Create a volume using the plugin.
|
||
This example mounts the `/remote` directory on host `1.2.3.4` into a
|
||
volume named `sshvolume`.
|
||
|
||
This volume can now be mounted into containers.
|
||
|
||
```bash
|
||
$ docker volume create \
|
||
-d cloudstor:azure \
|
||
--name cloudstorvolume
|
||
|
||
cloudstorvolume
|
||
```
|
||
|
||
4. Verify that the volume was created successfully.
|
||
|
||
```bash
|
||
$ docker volume ls
|
||
|
||
DRIVER NAME
|
||
cloudstor:azure cloudstorevolume
|
||
```
|
||
|
||
5. Start a container that uses the volume `cloudstorevolume`.
|
||
|
||
```bash
|
||
$ docker run --rm -v cloudstorevolume:/data busybox sh -c 'echo test > /data/test'
|
||
$ docker run --rm -v cloudstorevolume:/data busybox cat /data/test
|
||
test
|
||
```
|
||
|
||
6. Remove the volume `cloudstorevolume`
|
||
```bash
|
||
docker volume rm cloudstorevolume
|
||
|
||
cloudstorevolume
|
||
```
|
||
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
|
||
[command line reference](../reference/commandline/index.md).
|
||
|
||
|
||
## Developing a plugin
|
||
|
||
#### The rootfs directory
|
||
The `rootfs` directory represents the root filesystem of the plugin. In this
|
||
example, it was created from a Dockerfile:
|
||
|
||
>**Note:** The `/run/docker/plugins` directory is mandatory inside of the
|
||
plugin's filesystem for docker to communicate with the plugin.
|
||
|
||
```bash
|
||
$ git clone https://github.com/vieux/docker-volume-sshfs
|
||
$ cd docker-volume-sshfs
|
||
$ 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
|
||
$ docker rm -vf "$id"
|
||
$ docker rmi rootfsimage
|
||
```
|
||
|
||
#### The config.json file
|
||
|
||
The `config.json` file describes the plugin. See the [plugins config reference](config.md).
|
||
|
||
Consider the following `config.json` file.
|
||
|
||
```json
|
||
{
|
||
"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"]
|
||
}
|
||
}
|
||
```
|
||
|
||
This plugin is a volume driver. It requires a `host` network and the
|
||
`CAP_SYS_ADMIN` capability. It depends upon the `/docker-volume-sshfs`
|
||
entrypoint and uses the `/run/docker/plugins/sshfs.sock` socket to communicate
|
||
with Docker Engine. This plugin has no runtime parameters.
|
||
|
||
#### Creating the plugin
|
||
|
||
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
|
||
in subdirectory `rootfs`.
|
||
|
||
After that the plugin `<plugin-name>` will show up in `docker plugin ls`.
|
||
Plugins can be pushed to remote registries with
|
||
`docker plugin push <plugin-name>`.
|
||
|
||
|
||
## 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.
|
||
|
||
```bash
|
||
$ docker plugin install tiborvass/sample-volume-plugin
|
||
|
||
INFO[0036] Starting... Found 0 volumes on startup plugin=f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62
|
||
```
|
||
|
||
```bash
|
||
$ docker volume create -d tiborvass/sample-volume-plugin samplevol
|
||
|
||
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
|
||
```
|
||
|
||
```bash
|
||
$ 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
|
||
```
|
||
|
||
#### Using docker-runc to obtain logfiles and shell into the plugin.
|
||
|
||
`docker-runc`, the default docker container runtime can be used for debugging
|
||
plugins. This is specifically useful to collect plugin logs if they are
|
||
redirected to a file.
|
||
|
||
```bash
|
||
$ docker-runc list
|
||
ID PID STATUS BUNDLE CREATED
|
||
f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 2679 running /run/docker/libcontainerd/f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 2017-02-06T21:53:03.031537592Z
|
||
r
|
||
```
|
||
|
||
```bash
|
||
$ docker-runc exec f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 cat /var/log/plugin.log
|
||
```
|
||
|
||
If the plugin has a built-in shell, then exec into the plugin can be done as
|
||
follows:
|
||
```bash
|
||
$ docker-runc exec -t f52a3df433b9aceee436eaada0752f5797aab1de47e5485f1690a073b860ff62 sh
|
||
```
|
||
|
||
#### Using curl to debug plugin socket issues.
|
||
|
||
To verify if the plugin API socket that the docker daemon communicates with
|
||
is responsive, use curl. In this example, we will make API calls from the
|
||
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>`
|
||
|
||
|
||
```bash
|
||
curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/e8a37ba56fc879c991f7d7921901723c64df6b42b87e6a0b055771ecf8477a6d/plugin.sock http:/VolumeDriver.List
|
||
|
||
{"Mountpoint":"","Err":"","Volumes":[{"Name":"myvol1","Mountpoint":"/data/myvol1"},{"Name":"myvol2","Mountpoint":"/data/myvol2"}],"Volume":null}
|
||
```
|
||
|
||
```bash
|
||
curl -H "Content-Type: application/json" -XPOST -d '{}' --unix-socket /var/run/docker/plugins/45e00a7ce6185d6e365904c8bcf62eb724b1fe307e0d4e7ecc9f6c1eb7bcdb70/plugin.sock http:/NetworkDriver.GetCapabilities
|
||
|
||
{"Scope":"local"}
|
||
```
|
||
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
|
||
plugin is installed and `APICall` is the call to the plugin API.
|
||
|
||
For example, `http://localhost/VolumeDriver.List`
|