cURL docker through sockets
smac89
Posted on February 17, 2022
Did you know that the docker daemon exposes a gRPC api for communication OR that cURL can send data to unix sockets?
Let's see how this all works.
Docker engine
The underlying infrastructure of the docker ecosystem is the docker engine.
It is implemented using a client/server model (much like most unix tools are), and exposes its API over a gRPC interface. As usual in such model, there is usually only one server, and many clients, and the story is no different for docker.
Docker architecture. Image from https://docs.docker.com
The daemon acts as the server, while the CLI which we are all familiar with acts as one of the clients. The single point of communication is usually exposed as a unix socket, and communication is carried out via gRPC exchanging data in the form of protocol buffers.
cURL --unix-socket
It turns out that cURL is not just great for talking to HTTP servers, but it can apparently also do the same via UNIX SOCKETS.
Let's say we wanted to get the docker version currently installed; Normally you would do the following on the command line:
docker version
Using the api, we do something like
curl --silent --unix-socket /run/user/1000/docker.sock http://v1.41/version
Note the above socket path assumes you are running docker in rootless mode and your user id is 1000
. If running docker as root, the socket is likely to be located at /var/run/docker.sock
Which gives us:
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"20.10.12","Details":{"ApiVersion":"1.41","Arch":"amd64","BuildTime":"2021-12-13T11:46:12.000000000+00:00","Experimental":"false","GitCommit":"459d0df","GoVersion":"go1.16.12","KernelVersion":"5.13.0-28-generic","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"v1.4.12","Details":{"GitCommit":"7b11cfaabd73bb80907dd23182b9347b4245eb5d"}},{"Name":"runc","Version":"1.0.2","Details":{"GitCommit":"v1.0.2-0-g52b36a2d"}},{"Name":"docker-init","Version":"0.19.0","Details":{"GitCommit":"de40ad0"}}],"Version":"20.10.12","ApiVersion":"1.41","MinAPIVersion":"1.12","GitCommit":"459d0df","GoVersion":"go1.16.12","Os":"linux","Arch":"amd64","KernelVersion":"5.13.0-28-generic","BuildTime":"2021-12-13T11:46:12.000000000+00:00"}
How cool is that?!
You can take this even a step further, and expose a local docker daemon, over tcp to your friends over the internet. Here is a quick example which doesn't use cURL, but rather uses ncat:
server
ncat -kl -p 2376 -c 'ncat -U /run/user/1000/docker.sock'
client
curl http://localhost:2376/version | jq
One last thing to mention is that the format of the url ex. http://v1.41/version
is not strict. Any of the following would have given the same result:
http:/foo/version
http://dummy/version
http:/./version
The recommendation is to use the version of the API supported by docker as the first part of the url, then the actual commands come later.
Sources:
Posted on February 17, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.