Docker From A Distance – The Remote API
Many people use docker from the command line to build images, run containers and manage Docker on their machine. However, you can also run the same Docker commands via its remote REST API. In this blog I will guide you through Docker’s remote API using curl while pointing out a few details and tools that you might not know about. We will remotely search and pull an elasticsearch image, run a container and clean up after ourselves.
Docker’s Remote API
I assume you know how to build and run a Docker container via the command line. If not, check out Quinten’s blog post on how to create tomcat instances with Docker. When installing Docker the daemon is configured to listen on a UNIX socket. It’s fun to realize that we can access the REST API via the socket without any additional configuration. To list all images run the following command:
$ echo -e "GET /images/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock HTTP/1.0 200 OK Content-Type: application/json Content-Length: 858 Connection: close Date: Fri, 20 Dec 2013 16:02:41 GMT [{"Repository":"ubuntu","Tag":"12.04","Id":"8dbd9e392...", "Created":1365714795,"Size":131502179,"VirtualSize":131502179}, {"Repository":"ubuntu","Tag":"latest","Id":"8dbd9e392...", "Created":1365714795,"Size":131502179,"VirtualSize":131502179}, {"Repository":"ubuntu","Tag":"precise","Id":"8dbd9e392...", "Created":1365714795,"Size":131502179,"VirtualSize":131502179}, {"Repository":"ubuntu","Tag":"12.10","Id":"b750fe792...", "Created":1364102658,"Size":24653,"VirtualSize":180116135}, {"Repository":"ubuntu","Tag":"quantal","Id":"b750fe792...", "Created":1364102658,"Size":24653,"VirtualSize":180116135}]
You have to use netcat because you cannot echo to a socket from bash. For more information on communication with UNIX sockets in this way, see this Gist which has more code samples and useful links.
Listening on a port
To get Docker to listen on a port first stop docker.
$ sudo service docker stop
Now edit Docker’s upstart file at /etc/init/docker.conf so it looks like this:
description "Docker daemon" start on filesystem and started lxc-net stop on runlevel [!2345] respawn script /usr/bin/docker -H tcp://127.0.0.1:4243 -d end script
Now run
$ sudo service docker start
and Docker is listening on port 4243. However, note that this is insecure. Check out James Carr’s blog post on securing Docker’s remote API.
Example – Pulling, starting and stopping Elasticsearch
Let’s access the API with curl to see what is going on. We will run the following steps:
- Search for an elasticsearch image in the Docker index
- Pull an image from the Docker registry
- Create the container
- Start the container
- Stop the container
- Remove the container
Curious to know more about the Docker terminology like index and registry? Check this blog by Troy Howard.
Search
Let’s search for some elasticsearch images using the following call:
$ curl -s -XGET http://localhost:4243/images/search?term=elasticsearch | jq '.[] | .name' "paulczar/elasticsearch" "fgrehm/elasticsearch" "orchardup/elasticsearch" "mschoch/elasticsearch" "bacongobbler/elasticsearch" "mereghost/elasticsearch" "quintenk/elasticsearch" "coaxys/elasticsearch" "ehazlett/elasticsearch" ...
Here I filter the results through jq, a great tool for processing JSON on the command line. It’s like sed for JSON.
Pull an image
Now let’s pull the vieux/elasticsearch image:
$ curl -XPOST http://localhost:4243/images/create?fromImage=vieux/elasticsearch ... "progress":"[==================================================\u003e] 10.24 kB/10.24 kB 0","id":"daf68f48da59"} {"status":"Download complete","progressDetail":{},"id":"daf68f48da59"} {"status":"Download complete","progressDetail":{},"id":"daf68f48da59"}
Create a container
When running a container via the command line you would use the docker ‘run’ command. This is a composite command, consisting of the commands ‘create’ and ‘start’.
The remote API does not support the ‘run’ command. You have to execute ‘create’ and ‘start’ separately. To create a container run:
$ curl -X POST -H "Content-Type: application/json" http://localhost:4243/containers/create -d '{ "Hostname":"", "User":"", "Memory":0, "MemorySwap":0, "AttachStdin":false, "AttachStdout":true, "AttachStderr":true, "PortSpecs":null, "Privileged": false, "Tty":false, "OpenStdin":false, "StdinOnce":false, "Env":null, "Dns":null, "Image":"vieux/elasticsearch", "Volumes":{}, "VolumesFrom":"", "WorkingDir":"" }' {"Id":"d1fa1b772481441228b93a26cc7c384a9a08cb79ea5516f101faa89564e9c752"}
Start a container
To start the container we reuse the ID we got from the ‘create’ command.
$ curl -XPOST http://localhost:4243/containers/398378dfa8a5409c4ad011e96788e085d2f13bb6dff07c5394a955609fcf7327/start
and we can see that elasticsearch is running!
$ curl -X GET http://localhost:9200 { "ok" : true, "status" : 200, "name" : "Banner, Robert Bruce", "version" : { "number" : "0.90.5", "build_hash" : "c8714e8e0620b62638f660f6144831792b9dedee", "build_timestamp" : "2013-09-17T12:50:20Z", "build_snapshot" : false, "lucene_version" : "4.4" }, "tagline" : "You Know, for Search" } $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 398378dfa8a5 vieux/elasticsearch:0.90.1 /bin/sh -c elasticse 34 minutes ago Up 6 seconds 9200/tcp sharp_pasteur
Stop a container
And now let’s stop the container:
$ curl -X POST http://localhost:4243/containers/398378dfa8a5409c4ad011e96788e085d2f13bb6dff07c5394a955609fcf7327/stop $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Remove the container
Let’s clean up and remove the container:
$ docker ps -a | grep vieux 398378dfa8a5 vieux/elasticsearch:0.90.1 /bin/sh -c elasticse About an hour ago Exit 137 sharp_pasteur $ curl -X DELETE http://localhost:4243/containers/398378dfa8a5409c4ad011e96788e085d2f13bb6dff07c5394a955609fcf7327 $ docker ps -a | grep vieux $
The Docker phenomenon
Hope this post gave you a useful intro to Docker’s remote API. If you want to a more detailed description of the remote API check out the official Docker remote API documentation. Docker is becoming very popular. The community shares Dockerfiles, meetups pop up all over the planet and people keep pet whales and call them Moby Dock. Okay, maybe I am fibbing on that one. Point is, people like Docker because you can now do things that were impossible or very hard before. You could use a VMs instead but they can be cubersome and slow. Now you can encapsulate an entire application, including its code, configuration and environment and recreate and share it. Docker is actively developed and not production ready, but people see its potential and push its boundaries.
Feedback
Because of the potential we see in Docker we are interested in your feedback. How are you using Docker? What is your favourite use case? What are some downsides of Docker? If you had magic powers and you could….well if you had magic powers you wouldn’t use Docker you would just use your magic 😉 No but really, which feature would you like to see added to Docker and why? What do you think of our posts on Docker? Interesting, meh, or something else? Do you like to see more code, no code or good practices? Please let us know. We are looking forward hearing from you.
In closing I wish you happy holidays and a great new year!
P.S. Don’t forget to return your Docker configuration back to its original state.