Use Remote Docker Host With SSH
Being able to run Docker commands on a remote Docker host can be quite handy. However, one needs to do this in a secure manner, and setting up TLS verification is a complex pain. Luckily, this can quickly and easily be done through SSH which this tutorial will show you how to do.
Related Posts
Table of Contents
Setting up An SSH Key
In order for Docker to work over SSH, we need to set up an SSH key, as it will not work with using passwords for server authentication.
It is quite likely that you have already set up an SSH key for connecting to the remote host, but if you haven't, then create a key with:
ssh-keygen
... and add it to the remote host so that we can connect with it.
SSH Key Passphrase
We now have a choice. We can either make sure the key does not have a passphrase, in which case we we don't need to do anything extra. (If you already have a passphrase, you can remove it).
Alternatively, if we want to use a passphrase on the key, we need to add it to our SSH agent, which will prompt us for the passphrase.
ssh-add /path/to/private/key
If your key does have a passphrase, and you don't add it to your SSH agent, you will get an error message (see troubleshooting).
SSH Config
Now we need to add the details to our SSH configuration by editing our ~/.ssh/config
file.
Below is an example, but be sure to update the Host
, HostName
, Port
, IdentityFile
as appropriate to you.
Host docker1.mydomain.com
HostName docker1.mydomain.com
User my-remote-user
Port 2222
IdentityFile /path/to/private/key
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
- The control variables tell SSH to re-use the reuse the connection to the remote server using controlmaster directive [more info]. This was recommended by the Docker docs.
- The
HostName
can be the hostname, or the IP address of the remote server.
Docker Configuration Methods
We now have a choice of how we want to tell Docker to connect to the remote host over SSH. There is a quick and dirty method, or a cleaner one that makes use of Docker contexts.
Quick and Dirty Method (Temporary)
If you just need a really quick and easily solution, such as for within a CI/CD pipeline, then you can do the following:
SSH_USER=my-remote-user
SSH_HOST="docker1.mydomain.com:2222"
export DOCKER_HOST=ssh://$SSH_USER@$SSH_HOST
- The
SSH_USER
needs to be the name of a user on the remote host that has permissions to access the Docker socket (e.g. they are part of thedocker
group. This also needs to be the user you need to have set up the SSH key against. - I have specified the port in the
SSH_HOST
just to demonstrate how to do it if you are not using the default SSH port of 22. If you are using the default port, you do not need to specify:22
.
Now all of your docker commands will run on the remote host. E.g. try spinning up an ubuntu container:
docker run -it --name="my-ubuntu-instance" ubuntu /bin/bash
If you log into the remote host, you will see that it is running there.
Using Docker Contexts Method
A much cleaner solution is to use a Docker contexts which allow you to easily manage and switch between using different remote hosts.
We can create a new context by doing the following:
CONTEXT_NAME=docker-host1
REMOTE_HOST="ssh://docker-user@host1.example.com:2222"
docker context create \
--docker host=$REMOTE_HOST \
--description="My first remote engine" \
$CONTEXT_NAME
Now we can switch to using that remote engine for our future commands by running:
docker context use my-remote-engine
If we ever want to return to using our default local docker engine, then we would just run:
docker context use default
default
context,
but the one that was last set. This is unlike using the quick and dirty method.
docker context ls
.
Troubleshooting
If your SSH key has a passphrase, and you didn't add it to your SSH agent, you will get the following error message:
error during connect: Get "http://docker.example.com/v1.24/containers/json": command [ssh -l stuart -- 192.168.2.191 docker system dial-stdio] has exited with exit status 255, please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host: stderr=ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
stuart@192.168.2.191: Permission denied (publickey,password).
To fix, go back and read the SSH Key Passphrase section for your various choices.
References
- Protect the Docker daemon socket - Use SSH to protect the Docker daemon socket
- Visual Studio Code - Connect to remote Docker over SSH
First published: 25th August 2022