Remote Docker on DigitalOcean via OpenVPN

Docker logo

I'm doing a lot of development using Docker these days. Docker is bandwidth hungry so I prefer to run it remotely in the cloud, controlled locally by commands on my laptop.

This article explains how to get Docker set up remotely along with a VPN connection so it's easy to access container ports from your local machine instead of fiddling constantly with SSH port forwarding.


I chose DigitalOcean as my hosting provider because it's inexpensive.

  1. Install the one-click Docker application.
  2. Check the server's SSH host keys using the console to avoid a Man in the Middle attack.
  3. SSH to the server as root.


We're going to use OpenVPN. Don't be scared, I've provided all of the commands for you to copy and paste so configuration will be relatively quick and painless. I am assuming that you're not already using OpenVPN on your laptop (otherwise somethings may need to be changed below).

Install packages:

# apt-get install -y openvpn easy-rsa

Increase the security settings according to's recommendations:

# cd /usr/share/easy-rsa
# sed -i vars \
  -e 's/KEY_SIZE=2048/KEY_SIZE=4096/' \
  -e 's/CA_EXPIRE=3650/CA_EXPIRE=1826/' \
  -e 's/KEY_EXPIRE=3650/KEY_EXPIRE=365/'

Create the certificates:

# source ./vars
# ./clean-all
# ./build-dh # This is going to take a long time.
# ./pkitool --initca
# ./pkitool --server server
# ./pkitool client
# cp keys/{dh4096.pem,ca.*,server.*,client.crt,client.key} /etc/openvpn/

Configure the server:

# cd /etc/openvpn
# openvpn --genkey --secret ta.key
# zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz | sed \
  -e 's/dh1024.pem/dh4096.pem/' \
  -e 's/;tls-auth ta.key 0/tls-auth ta.key 0/' \
  -e 's/;user nobody/user nobody/' \
  -e 's/;group nogroup/group nogroup/' > server.conf
# service openvpn start

Tell Docker to listen to the VPN connection. The --ip parameter instructs Docker not to expose container ports to the Internet—only to the VPN. This is what I want for development work; your needs may vary.

# sed -i 's/#DOCKER_OPTS="--dns --dns"/DOCKER_OPTS="-H tcp:\/\/ --ip"/' /etc/default/docker
# service docker restart


# ip=$(ifconfig eth0 | grep inet | cut -d : -f 2 | cut -d ' ' -f 1)
# sed /usr/share/doc/openvpn/examples/sample-config-files/client.conf \
  -e "s/my-server-1/$ip/" \
  -e 's/;user nobody/user nobody/' \
  -e 's/;group nogroup/group nogroup/' \
  -e 's/;tls-auth ta.key 1/tls-auth ta.key 1/' > client.conf

Now set up an OpenVPN client on your computer. I'm on Mac OS so I'm using Tunnelblick.

Type the following commands on your laptop but don't close the SSH connection to the server yet because we'll need to do some clean up at the end.

$ mkdir ~/Desktop/Docker.tblk
$ ssh root@<ip address of server> 'cd /etc/openvpn; tar -c ca.crt client.* ta.key' | tar -C ~/Desktop/Docker.tblk -x

Now double-click on the Docker.tblk file on your Desktop to install the VPN connection configuration. After it's installed you may delete the Docker.tblk file.

When you connect, Tunnelblick will ask you if you want to use the 'down-root' plugin. Choose Always use the plugin.

Install Docker (this instruction is for Mac OS using Homebrew):

$ brew install docker

Tell Docker to use the remote daemon:

$ echo 'export DOCKER_HOST=tcp://' >> ~/.bash_profile
$ source ~/.bash_profile 

Now you can issue Docker commands on your local computer to control your Docker running in the cloud:

$ docker info
Containers: 0
Images: 0
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 0
Execution Driver: native-0.2
Kernel Version: 3.13.0-40-generic
Operating System: Ubuntu 14.04.1 LTS

Yay! Celebrate!

a man celebrating

When you expose ports from your containers you now have access to them without having to worry about manually forwarding ports via SSH. For example, you can run Nginx and bind it to port 8080 on the host:

$ docker run -it -p 8080:80 nginx:latest

You can see the welcome page from the browser on your laptop by visiting If you don't want to remember to type each time, you can do the following to make a hostname for it:

$ printf "\tdocker\n" | sudo tee -a /etc/hosts

Now you can visit http://docker:8080 instead. Feel free to choose a hostname other than docker if you like.

Finally, do a little bit of clean-up on the server:

# rm client.*

That's it! Please let me know if you have any questions or enhancements in the comments below. Docker on!

View or Post Comments