Remote access to Docker with TLS

By default Docker is available only on UNIX socket. Because UNIX sockets cannot be forwarded through SSH, you generally had 3 options:

  1. Hack nginx to forward traffic to Docker
  2. Use SSH and socat to tunnel connection
  3. Make Docker daemon listen on exposed port

1st solution is really cumbersome to setup. 2nd requires socat installed on both server and client. 3rd is not secure and anyone can connect or intercept Docker traffic as connection is not encrypted.

The situation was hopeless until Docker implemented TLS auth in 0.10.

I present few simple steps to setup it:

I. Generate your certificates

You need to generate 3 kinds of certificates:

  • CA certificate used for generating client and server certs
  • Client certificate used by remote Docker client
  • Server certificate used by Docker daemon on server

I wrote a little Ruby script that generates all three certificates for you. All you need to do is clone this repository and run following commands:

$ gem install certificate_authority
$ ruby certgen.rb example.com
CA certificates are in ~/.docker/ca
Client certificates are in ~/.docker
Server certificates are in ~/.docker/example.com

Certificates should be now available under ~/.docker path.

II. Copy server certificates to remote location

The script generated keys and certificates required by Docker daemon ~/.docker/example.com (example.com is your domain name).

Copy them on your server to ~/.docker directory:

rsync -ave ssh ~/.docker/example.com/ [email protected]:~/.docker/

III. Configure Docker on remote location

Docker daemon since version 0.10 supports --tlsverify mode that enforces encrypted and authenticated remote connections.

I assume you're using Ubuntu 12.04 LTS with Docker already installed and running. Instructions for other distros may be little different.

All you need to do is add following line to /etc/default/docker:

DOCKER_OPTS="--tlsverify -H=unix:///var/run/docker.sock -H=0.0.0.0:4243 --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/cert.pem --tlskey=/root/.docker/key.pem"

And restart Docker daemon with:

service docker restart

If something went wrong Docker daemon won't start again. You can debug it by browsing logs under /var/log/upstart/docker.log.

That's it!

You can connect to remote Docker instance using --tlsverify flag:

docker --tlsverify -H tcp://example.com:4243 images

It will use certificates stored in ~/.docker. To use different ones, you can use --tls* options listed in docker --help and documentation.

The official guide of TLS setup can be found on Docker site.