Forward a docker unix socket on a remote host to our local machine

ThomasThomas
3 min read

Docker relies on a unix socket to interact with the docker daemon. It is often located in /var/run/docker.sock.

Being able to manage docker on a remote host without going through a shell on the remote system typically requires changing the docker configuration or adding a service to systemd to open a port (TCP). It then needs to be secured to prevent unauthorized access.

Forwarding the unix socket doesn't require any such change.

We'll forward the unix socket from the remote host with docker installed, on a host that just has the docker executable. Aside from the SSH server, no TCP port will need to be listening anywhere.

SSH enters the game

SSH has the ability to do forwarding and can be done by both sides:

  • From local to remote (-L): connecting a remote host and forwarding a port that machine has access to. It is often done to forward a port on the local machine, but it can be any other system that machine has access to.

  • From remote to local (-R): Connections to a given TCP port or Unix socket on a remote (server) host are to be forwarded to the local side.

While we typically deal with TCP connections, it can also forward unix sockets, and we can mix and match:

  • TCP to TCP

  • TCP to unix socket

  • unix socket to TCP

  • unix socket to unix socket

As a side note, UDP connections can also be forwarded, but it needs a bit of help from eithermkfifo, or with socat.

Let's get our hands dirty

This is done with two commands on our local machine.

The first one, with ssh, will initiate the connection and forward the socket, and the second one will indicate to docker where to find its socket.

Step 1: SSH forwarding

We need first to ensure the user on the remote host has access to docker.

To do the forwarding, we just have to add -L <LOCAL_DOCKER_SOCK_PATH>:<REMOTE_DOCKER_SOCK_PATH> to the command we typically use to connect to that remote server.

Here is what it can look like in practice when we create the fordwarded docker socket in the home directory of our user:


ssh -L ~/docker.sock:/var/run/docker.sock bob@192.168.1.100

In this command, we're connecting to 192.168.1.00 with the username bob. Nothing unusual. Now, comes the part with the -L:

  • The first part, before the colon, is where we'll put the docker unix socket on our local system, in our home directory, in the file docker.sock.

  • The second part, after the colon, indicates where is the socket on the remote host. In this case, it's in /var/run/docker.sock.

We'll need to leave the connection open for the time being. There are a few parameters that can be used keep the connection 1. in the background and 2. alive, but that's a story for another time.

Step 2: Docker host environment variable

Assuming we access to a docker executable, whether it was copied from another installation of the same OS, or from our local docker installation, we just have to set an environment variable to indicate where to look for the unix socket.

Since it's in our home directory, we need to run the following command:

export DOCKER_HOST=unix://$(pwd)/docker.sock

Voilà.

Profit

Now, when interacting with dockeron our local machine, all the operations will be done on the remote host. There is no configuration change needed on the remote host.

It is even possible to push this further and chain SSH connections.

A couple things

  1. The unix socket doesn't get deleted on our local machine when the SSH connection is disconnected or dropped.

  2. It goes without saying that the export command just changes it in the current shell, and isn't permament.

0
Subscribe to my newsletter

Read articles from Thomas directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Thomas
Thomas