What is this about?
Docker is no longer the exotic new kid in the playground. A huge number of companies are adopting it in their development as well as deployment environments.
With this increasing usage, the number of use cases for this technology are also evolving. One of them is to be able to connect to a docker daemon running on a remote server. Here, one may suggest to simply SSH to the remote server running the docker daemon and execute whatever commands or scripts one may desire. While not a bad idea, it does not works very well if we want to connect to multiple docker daemon's running on different hosts and get docker host information simultaneously.
This is where Docker Remote API's come to help us. Since docker version 1.6.x docker introduced REST apis to query the docker daemon. In default docker installations, remote api feature is disabled.
In this article, we will explore how to enable docker remote APIs on a linux distribution and connect to it remotely using SSH Tunnel.
Enabling Docker Remote API
In 14.04, Ubuntu uses upstart as the process manager. By default, upstart jobs are located in /etc/init and the docker Upstart job can be found at /etc/init/docker.conf. A simple search in docker.conf for DOCKER_OPTS should reveal an unassigned DOCKER_OPTS variable.
This variable needs to be given a value so that:
DOCKER_OPTS='-H tcp://<IP_ADDRESS>:4243 -H unix:///var/run/docker.sock'
Replace <IP_ADDRESS> with the IP address from which we will be connecting with the docker daemon's API. Providing any external IP address will also need us to expose our port 4243 publicly or atleast over a VPN. Neither of which is a very secure method (specially exposing the port publicly). But still if we don't care much about security for just this once, we can use 0.0.0.0 to allow docker daemon to accept requests from any IP address.
For a production environment however, it is imperative that security should be paramount. Hence, we will be creating a SSH tunnel with the docker host (i.e. the remote server on which we are enabling remote API). Since creating a SSH tunnel to the remote host will effectively put us in the host's local environment, we can configure docker daemon to accept requests only from the local IP i.e. 127.0.0.1
Connecting via SSH tunnel only needs the port 22 (default ssh port) to be exposed which in any case is needed to be able to connect to a remote host.
By default the Docker daemon listens on unix socket unix:///var/run/docker.sock and the client must have root access to interact with the daemon. Hence, the user we would be using to create an SSH tunnel should have root access.
Once the file has been properly configured, we will have to restart the docker service with:
sudo service docker restart
To verify if remote APIs have been enbaled. We can make an API call from the terminal on the host itself about information about all the docker images on the host.
curl -X GET http://127.0.0.1:4243/images/json
This should print an array of JSONs to the stdout.
Creating SSH Tunnel to the remote host
Creating an SSH tunnel is a very starightforward process. All we will need is SSH login credentials of a user with root access. Assuming our user's name is ubuntu, our tunnel command would be:
ssh -f ubuntu@<HOST_IP_ADDRESS> -L 4244:127.0.0.1:4243 -N
Here, <HOST_IP_ADDRESS> is the public IP address of the remote host machine. Above command would create an SSH tunnel between the remote host's port 4243 and our localhost 4244.
For users connecting to AWS EC2 servers using .pem file with user ubuntu:
ssh -i <PATH_TO_PEM_FILE> -f ubuntu@<PUBLIC_DNS_NAME> -L 4244:127.0.0.1:4243 -N
Replace <PATH_TO_PEM_FILE> with the path to the .pem file and <PUBLIC_DNS_NAME> is the ec2 instance id.
If successfully done, we should be able to make API calls on out localhost to port 4244.
curl -X GET http://127.0.0.1:4244/images/json