Within the Docker ecosystem there are three APIs available. These are the registry API, the Docker Hub API and the Remote API. The Registry API offers a way of working with the Docker registry which acts as the image repository. The Docker Hub API offers a way of working with the Docker Hub, while the Remote API offers a way of working with the daemon. In this article, we will only discuss the Remote API because of the features it provides for working with Docker.
By default the Docker daemon which provides the remote API binds on socket unix:///var/run/docker.sock. To have all the resources requires the daemon to run with all root privileges. If there is a docker group on the host OS, ownership of the daemon socket is assigned to docker group enabling all docker users to run Docker without requiring root privileges. This is not a security vulnerability when the API is used on the host running Docker. When using the Docker API remotely, there is a security vulnerability so we need to make adjustments by binding the daemon to a network interface. This adjustment is done by editing the startup configuration files belonging to the daemon. On ubuntu and Debian the configuration file is stored as /etc/default/docker, when using Upstart the configuration file is stored as /etc/init/docker.conf file. If you are running Red Hat, Fedora and similar systems the configuration file is saved as /etc/sysconfig/docker, and for systems with systemd, it is stored as /usr/lib/systemd/system/docker.service.
On the configuration file, we need to change the entry ExecStart=/usr/bin/docker -d to ExecStart=/usr/bin/docker -d -H tcp://0.0.0.0:2200. Open the file in your favorite text editor and make the changes. In this tutorial, we can use gedit to open the configuration file by running the command below. Make the changes, save and close the file.
sudo gedit /etc/default/docker
For the changes to take effect we need to restart the daemon using the command below
sudo systemctl --system daemon-reload
After editing the configuration file we also need to make changes in the firewall to enable TCP communication on your specified port. To connect to a remote host we use the -H flag and specify where the daemon is running and the command we would like to execute. For example, to connect to a daemon running at example.com and get information we would use the command shown below.
sudo docker -H docker.example.com:2200 info
Once connectivity to the daemon is established the curl command can then be used to pass commands. The previous command can be implemented using curl as shown below which specifies info as our end point.
The above command will return the daemon system information.
To use the API to return a list of images on the daemon, we would use the command below.
The above command provides the same information that docker images provides. To get specific images we provide the image ID. An example of how we can use a specific image ID is shown below.
curl d0178048e904fee25354db77091b935423a829f171f3e3cf27f04ffcf7cf56/ json
To search for images on the Docker hub we just need to specify the name of the image. In the example below, we are searching for the wordpress images.
curl "http://docker.example.com:2200/images/search?term= wordpress"
Other operations that are possible with the API are building, removing and updating images like we can do on the command line.
Any container management activities that can be accomplished on the command line are also possible when using the Remote API. To get a list of all running containers on the daemon we use the container command as shown below.
curl -s “http://docker.example.com:2200/containers/json”
To return a list of running and stopped containers, we need to use the all flag and set it to 1. This is shown in the command below.
The examples demonstrated so far are just some of the ways we can use the Remote API. For an exhaustive lis of what is possible through the API the reader is referred to the API documentation which is available here .
To execute the commands we previously demonstrated there was no requirement of authentication. This is a very big security risk because any one can execute commands. To prevent this we need to enable authentication. TSL/SSL certificates are used to enforce a secure remote connection. To implement authentication we can rely on certificate authority (CA) or a PKI infrastructure. In this tutorial, we will demonstrate how to implement a local CA but it is important to note it does not provide capabilities available in a dedicated CA.
To create a CA certificate and a key, the openssl library has to be installed. Check this by running the code which openssl at a terminal. If the directory it has been installed will be shown.
Create a directory where we will store our key. Move to the directory and generate a key specifying a pass phrase. The pass phrase will be used in creating and signing certificates.
We need to create a CA certificate using the command below. Provide the requested information.
sudo openssl req -new -x509 -days 365 -key ca-key.pem -out ca.pem
We will use the CA certificate created above to create a Docker server and key. The command below will create the server key. You will be required to provide a pass phrase.
sudo openssl genrsa -des3 -out server-key.pem
After creating the server key we need to create a certificate signing request (CSR). The command below will create a CSR. You will be required to provide a pass phrase.
sudo openssl req -new -key server-key.pem -out server.csr
The command below signs CSR and generates server certificate.
sudo openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem
We now need to edit the configuration file to ensure TLS is enabled and specify where the CA certificate and key are located. Open the configuration file and add the entry below.
sudo gedit /etc/default/docker
ExecStart=/usr/bin/docker -d -H tcp://0.0.0.0:2376 –tlsverify – tlscacert=/etc/docker/ca.pem –tlscert=/etc/docker/server-cert. pem –tlskey=/etc/docker/server-key.pem
In this article we introduced the three docker APIs and how they are useful. We limited our discussion to the Remote API. We demonstrated how to use the API to accomplish tasks performed on the command line. We discussed how to implement authentication and to ensure remote connections are secure.