Docker push via ssh tunnel
A standard docker push command (docs) looks like this:
#!/bin/bash
docker push {registry hostname}:{listening port}/{image name}:{image tag}
docker push registry.mydomain.com:5000/really_cool_image:3.1.2
But this assumes that the registry is accessible via your network. If it wasn’t, your push command would fail. Let’s say that your docker registry is running on a server whose firewall denies most incoming connections - you can only access it over ssh.
Setup an ssh tunnel from your local machine to the remote server. In this example the registry is listening on port 5000 of the server.
$ ssh -f -N -L 5000:localhost:5000 -l my_username registry.mydomain.com
Options explained:
- -f puts ssh into background mode
- -N means that no command will be run on the remote machine, we’re just forwarding traffic
- -L port:host:host_port
- -l is the username you want to use on the remote machine. Leave it out to use your current username.
Now, traffic directed to localhost:5000 will be forwarded to registry.mydomain.com:5000 over the ssh tunnel.
You can now run docker push like this:
$ docker tag really_cool_image:3.1.2 localhost:5000/really_cool_image:3.1.2
$ docker push localhost:5000/really_cool_image:3.1.2
Doing this on macOS
If you try to do the above with docker for mac, you’ll probably find yourself with an error like this:
The push refers to a repository [localhost:5000/really_cool_image]
Put http://localhost:5000/v1/repositories/really_cool_image/: dial tcp 127.0.0.1:5000: getsockopt: connection refused
What’s happening here is that docker can’t access the ssh tunnel you setup on the mac, because of the way Docker works on macOS. Essentially, your mac and docker have
two different 127.0.0.1
addresses. You can get around this by explicitly setting up the ssh tunnel within docker instead
of on your mac. First, open Docker’s own terminal via screen:
screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
Hit enter and you should see a / # appear. You can now setup the ssh tunnel from within Docker itself:
ssh -f -N -L 5000:localhost:5000 -l my_username registry.mydomain.com
Once that’s setup, you should be able to run your normal docker push
command from
the macOS terminal.