Automate Docker with the Remote API and Ruby(P1)

Docker is a really nifty tool to have under your belt. It’s been used by many developers to ease the process of development. We have done many topics for Docker, you can check them here. If you have not yet installed Docker on your machine, you can find out how via those articles or on Docker’s site.

In this post, I am going cover Docker’s Remote API. If you used Docker up to this point, it’s likely been via the command-line interface which is actually a client that uses the Remote API. By the way, I presume that you understand all the basics of Docker. If not, please read the articles I link to above.

Before we can interact with the API we have to configure Docker to listen on a specific TCP port. Let’s edit the Docker config file:

Path: /etc/init/docker.conf

Add this line:

DOCKER_OPTS='-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock'

Restart docker:

service docker restart

Now we can connect to our Docker server using port 4243. Let’s test our connection to the server before proceeding. This can be accomplished with the command line tool curl

curl -X GET http://139.59.148.228:4243/images/json

This will print all the images we have on our Docker server. I tend to prefer to use a REST Client when dealing with more data:

![RESTClient add-on for Firefox](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/07/1468603710rest-client.png)

RESTClient add-on for Firefox

This confirms that we can access our Docker server.

Ruby

Let’s get to the Ruby part. We are going to use the docker-api gem. This will allow us to have an object oriented interface to the Docker Remote API.

We can install it directly from our terminal:

gem install docker-api

Or add it to the Gemfile:

gem "docker-api" # followed by a `bundle install`

We will use IRB (Interactive Ruby Shell) throughout the tutorial, but any of the examples can be done in a Ruby file.

First step is to import the docker-api gem:

require 'docker-api'

Point it to our docker server:

Docker.url = 'tcp://139.59.148.228:4243/'

Let’s test our connection now, this can be easily done by using the version method:

Docker.version
=> {"Version"=>"1.11.1", "ApiVersion"=>"1.23", "GitCommit"=>"5604cbe", "GoVersion"=>"go1.5.4", "Os"=>"linux", "Arch"=>"amd64", "KernelVersion"=>"3.13.0-85-generic", "BuildTime"=>"2016-04-26T23:30:23.291099901+00:00"}

The server responds with some information for the host system of the Docker server.If you get an error complaining “Connection Refused” like so:

Excon::Errors::SocketError: Connection refused - connect(2) for 139.59.148.228:42432 (Errno::ECONNREFUSED)

Then you probably have a problem with the server. Note: Check if you are connecting to the right port and make sure if you have a firewall configuration that allows connections to that particular port.

Docker Images

Manipulating with images is very easy:

image = Docker::Image.create('fromImage' => 'rails:4.2')

This might take some time depending on the network connection, it will pull the Rails image fromDocker Hub.

Something worith noting here: we are separating Rails and the version (4.2) we want. This is a Docker image name and tagging convention that works for many other docker images, such as ruby:latest ordebian:latest.

Let’s make sure we have the image on the server. SSH into your Docker server (this is likely just your local box) and run:

$ docker images

Quick tip: if you have downloaded a lot of images you can run:

$ docker images | grep ruby

This will now only list images that have the word ruby. The output might look something like this:

ruby                latest               2d43e11a3406        2 weeks ago         729.1 MB`

The information shown is:

  • The name of the repository
  • The tag or the version of the image, this can be specified as a number or name like ruby:latestorruby:1-wheezy
  • The image ID
  • The creation date
  • the size.

This confirms that we have successfully pulled an image. Now let’s see what images we have in our Docker server via the API. If we execute the Image.all method we will get a JSON representation of our images:

Docker::Image.all
=> [#<Docker::Image:0x00000001834e28 @id="sha256:299e53ed9d2a9d07391855b2f49a823af145c1cf66bd711968b3b2ccc29d49d8", @info={"ParentId"=>"", "RepoTags"=>["rails:4.2"], "RepoDigests"=>nil, "Created"=>1464136334, "Size"=>837203335, "VirtualSize"=>837203335, "Labels"=>{}, "id"=>"sha256:299e53ed9d2a9d07391855b2f49a823af145c1cf66bd711968b3b2ccc29d49d8"}, @connection=#<Docker::Connection:0x0000000176c6f8 @url="tcp://139.59.148.228:4243/", @options={}>>, #<Docker::Image:0x00000001834cc0 @id="sha256:31e17b0746e48958b27f1d3dd4fe179fbba7e8efe14ad7a51e964181a92847a6", @info={"ParentId"=>"", "RepoTags"=>["tutum/hello-world:latest"], "RepoDigests"=>nil, "Created"=>1450109804, "Size"=>17791668, "VirtualSize"=>17791668, "Labels"=>nil, "id"=>"sha256:31e17b0746e48958b27f1d3dd4fe179fbba7e8efe14ad7a51e964181a92847a6"}, @connection=#<Docker::Connection:0x0000000176c6f8 @url="tcp://139.59.148.228:4243/", @options={}>>]

Containers

Creating and running instances of these images as containers is also possible:

container = Docker::Container.create('Image' => 'ubuntu', 'Tty' => true)

This will create a container with the Ubuntu image we have on our server. Note the ‘Tty’ => true part thatl checks that our container is running via SSH. If we don’t add the Tty parameter, then our container will exit, since it’s just a process and it will die (exit).

=> #<Docker::Container:0x000000025f6bb0 @id="5bbf21e99459052a816cd74006aec00a53cf9bd0814d5517804257a5869f3329", @info={"Warnings"=>nil, "id"=>"5bbf21e99459052a816cd74006aec00a53cf9bd0814d5517804257a5869f3329"}, @connection=#<Docker::Connection:0x00000002541b98 @url="tcp://139.59.148.228:4243/", @options={}>>

The container is created, we need to start it:

container.start

Time to check and see if our container is running. Go back to the shell session and run this command:

$ docker ps
ba13a1bfb728 ubuntu "/bin/bash" 1 minutes ago Up 52 seconds pedantic_torvalds

We have have confirmed that our Docker container is running. Now from the API back in irb:

container.top
=> [{"UID"=>"root", "PID"=>"28267", "PPID"=>"28248", "C"=>"0", "STIME"=>"12:43", "TTY"=>"pts/5", "TIME"=>"00:00:00", "CMD"=>"/bin/bash"}]

We get a simplified return value representing the running container. There are also some other methods you can use for stopping, restarting, and pausing the container. Check out the documentation for more details on them.

Source : https://codequs.com/p/HyKd4uiv/automate-docker-with-the-remote-api-and-ruby/