Extending Docker

$ whoami

Lorenzo Fontana

Software Engineer at Facile.it

https://github.com/fntlnz

https://twitter.com/fntlnz

http://fntlnz.wtf

http://engineering.facile.it

http://jobs.facile.it

In Docker batteries are included

but you can change them, if you whish!

How?

With plugins!

What are Docker plugins ?

Out of process extensions which adds capabilities to the Docker Engine.

What kind of capabilities?

Authorization

VolumeDriver

Network

IPAM

What we did before plugins?

Wrap the Docker Remote API

Wrap the Docker Remote API

Wrap the Docker Remote API

Wrap the Docker Remote API

Ok but, how do they work?

The plugin implements an HTTP server which can be discovered by Docker

The HTTP server exposes a set of RPCs issued as HTTP POSTs with JSON payloads

Docker makes a request to the plugin whenever is needed

Plugin discovery

Docker will always first check for unix sockets first (*.sock) by looking in the /run/docker/plugins folder

Then it will check for specifications files
like *.spec and *.json
in /etc/docker/plugins or /usr/lib/docker/plugins

JSON Specification *.json

/etc/docker/plugins/example-plugin.json


{
  "Name": "example-plugin",
  "Addr": "https://fntlnz.wtf/example-plugin",
  "TLSConfig": {
    "InsecureSkipVerify": false,
    "CAFile": "/usr/shared/docker/certs/example-ca.pem",
    "CertFile": "/usr/shared/docker/certs/example-cert.pem",
    "KeyFile": "/usr/shared/docker/certs/example-key.pem",
  }
}
                        

Text files containing an URL *.spec

/etc/docker/plugins/example-plugin.spec


                            tcp://[::]:8080
                        

                            unix:///path/to/my/plugin.sock
                        

Plugin API

Handshake:

POST /Plugin.Activate

Response:


{
    "Implements": ["VolumeDriver"]
}
                        

Available protocols are:

  • authz
  • NetworkDriver
  • VolumeDriver
  • IpamDriver

Each protocol provides its own set of RPC calls in addition to the activation call

Error handling

Is done via the response error form


{
    "Err": string
}
                        

That should be used along with the HTTP error statuses 400 and 500

VolumeDriver Plugins

VolumeDriver plugin protocol

Plugins that provide volume capabilities must register themselves as VolumeDriver during the Handshake


{
    "Implements": ["VolumeDriver"]
}
                    

A VolumeDriver plugin is expected to provide writable paths on the host filesystem

A volume plugin makes use of the flags:

-v : to specify the volume name

--volume-driver : to specify the driver


docker run -ti \
  -v volumename:/folder \
  --volume-driver=myplugin \
alpine sh
                        

VolumeDriver protocol

/VolumeDriver.Create

/VolumeDriver.Remove

/VolumeDriver.Mount

/VolumeDriver.Path

/VolumeDriver.Unmount

/VolumeDriver.Get

/VolumeDriver.List

WAIT!

There's nothing from Docker that can help me implementing this?

Yay! github.com/docker/go-plugins-helpers

Demo

hope that everything works as expected

Some useful volume plugins

Flocker:

https://clusterhq.com/docker-plugin

GlusterFS plugin:

https://github.com/calavera/docker-volume-glusterfs

IPFS plugin:

http://github.com/vdemeester/docker-volume-ipfs

OpenStorage plugin:

https://github.com/libopenstorage/openstorage

NetworkDriver plugins

NetworkDriver plugin protocol

Plugins that provide network capabilities must register themself as NetworkDriver during the Handshake


{
    "Implements": ["NetworkDriver"]
}
                    

This indicates that the plugin should be registered with LibNetwork as driver

Container Network Model

Network

/NetworkDriver.CreateNetwork

/NetworkDriver.DeleteNetwork

Endpoint

/NetworkDriver.CreateEndpoint

/NetworkDriver.EndpointOperInfo

/NetworkDriver.DeleteEndpoint

Sandbox

/NetworkDriver.Join

/NetworkDriver.Leave

Some useful network plugins

Weave:

https://github.com/weaveworks/weave

Onion:

https://github.com/jfrazelle/onion

Contiv Networking:

https://github.com/contiv/netplugin

Thanks for listening

Questions?