As we saw in Part I, we can easily secure HTTP connections using SSH tunnels. Similarly, we could apply the same strategy to communicate with a server running a Docker daemon. Since we’ll be doing this with Python, to communicate with docker we will use docker-py.
Let’s say that we want to connect from mycomputer (which is in a LAN where other users are connected, like in Part I) to a remote dockerdeamon to execute docker commands using docker-py, as shown in (Fig.1). For this example, let’s pretend that we would like to list all the docker images in dockerdeamon. First, we need to install docker-py via pip in mycomputer.
bernardo@mycomputer:~$ pip install docker-py
By default, docker daemon listens on unix:///var/run/docker.sock to allow only local connections by the root user. For remote access, we need to tell the daemon to listen on 0.0.0.0:5555 in order to give remote access, through TCP port 5555. We can do this by editing the file /etc/default/docker in dockerdaemon:
DOCKER_OPTS="-H unix:///var/run/docker.sock -H tcp://0.0.0.0:5555"
We load this new configuration and enable the docker daemon service executing the following command in dockerdaemon:
dockerdaemon_user@dockerdaemon:~$ sudo service docker start
Then, we create a python script to achieve our request.
import docker def list_images(host,port): client = docker.Client(base_url="http://%s:%s" % (host,port)) return client.images() if __name__ == '__main__': remote_docker_daemon_host = "dockerdaemon" default_docker_port = 5555 print list_images(remote_docker_daemon_host, default_docker_port)
If we execute this python script, you guessed it right, it will print all the docker images in dockerdaemon. Any of the other users connected to our LAN could also send commands to our dockerdaemon. Potentially, they could also eavesdrop our communication and know what are we doing with docker (same problem as in Part I). But what matters most in this situation and what we would like to avoid (see Fig.1) is that anyone who is aware of the existence of docker daemon listening on port 5555 can interact with it, whether they are part of our LAN or not, simply by being connected to the Internet. By doing this, a malicious individual could execute any command they wish to the docker daemon, who would simply listen and execute. These issues can be overcome using SSH tunnels.
As a first step, we will need to install openssh-server in the dockerdaemon server and append our public key into:
This allows us to connect from mycomputer using our private key through ssh. Then, we will open the port TCP 22 to allow us to connect via ssh and we will block any other port (even docker daemon port TCP 5555), thus malicious individuals cannot execute any command in dockerdaemon.
Futhermore, we will need to add the bgtunnel module to our python script to create SSH tunnels in python.
bernardo@mycomputer:~$ pip install bgtunnel
After that, we modified our python script to do our remote docker request through a SSH tunnel as follows:
import docker import bgtunnel def list_images(host,port): forwarder = bgtunnel.open(ssh_user=dockerdaemon_user, ssh_address=host, host_port=str(port)) client = docker.Client(base_url="http://localhost:%d" % forwarder.bind_port) return client.images() if __name__ == '__main__': remote_docker_daemon_host = "dockerdaemon" default_docker_port = 5555 print list_images(remote_docker_daemon_host, default_docker_port)
First, we open an SSH tunnel to dockerdaemon using bgtunnel giving us the local bound port to send commands through forwarder.bind_port. Then, we send all docker requests through this tunnel creating a new docker client through localhost:forwarder.bind_port. By doing this, nobody except a user that holds the right SSH certificate can connect and send request to the dockerdaemon. Thus, we avoid other local users potentially eavesdropping or intercepting our remote docker requests, as well as any user in the Internet communicating with our dockerdaemon.
That should be all for now. I hope it helps you communicating with your docker daemon remotely and securely. If you have any questions, please comment below or reach out to me directly on twitter at @bebespaniard.