Docker TLS encrypted connection
April 09, 2016
This is a short summary of Protect the Docker daemon socket from the official Docker documentation
Observations:
- All servers trust all connections from clients that have been signed by the same CA. If you'd like to be selective about which clients are allowed to connect to which servers, you'll need to setup a new CA for every server, and issue client certificates for each client.
- The Docker daemon and client only needs access to the CA public key to validate incoming client connections. The private key can be stored securely elsewhere/offline.
- Standard Docker daemon port is 2375. TLS secured Docker daemons should run on port 2376
Conventions
- In this guide, I'll use the file extension
.keyfor private keys, and.pemfor public keys. - I'll use the name
docker1.example.comfor all references to the hostname that is running the Docker daemon. Be sure to replace this with your actual hostname in order for this to work.
Create a CA
You'll first need to create a CA (Certificate Authority) for your Docker servers and clients. A CA (in short) is simply a top-level certificate that will be used to sign all CSR's, and is trusted by all servers and clients.
Create a directory for your CA:
mkdir ~/dockerca
cd ~/dockercaGenerate the private key for your CA ca.key:
openssl genrsa -aes256 -out ca.key 4096You'll be asked to enter a passphrase. This is required.
Create a public key ca.pem for your CA, based on it's private key ca.key:
openssl req -new -x509 -days 365 -key ca.key -sha256 -out ca.pemYou'll be asked several questions (like Country, State/Province, Locality/City, Organization Name and Unit, Email).
You can either choose to accept the defaults, leave them empty, or enter any value applicable to you. These values will be embedded in the public key, but are not relevant for TLS to work correctly.
EXCEPT for one value Common Name, enter the public hostname for which you want your Docker daemon to be accessible.
Create a key and CSR for your Docker server
Replace the example docker1.example.com below for your own servername.
IMPORTANT Make sure they match the hostname you will use to connect to your Docker daemon.
openssl genrsa -out docker1.example.com.key 4096
openssl req -subj "/CN=docker1.example.com" -sha256 -new -key docker1.example.com.key -out docker1.example.com.csrSign the server CSR with your CA
First, create a new extfile.cnf containing the IP addresses of your Docker server:
echo subjectAltName = IP:10.10.10.20,IP:127.0.0.1 > extfile.cnfNext, we'll sign the CSR using the CA:
openssl x509 -req -days 365 -sha256 -in docker1.example.com.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out docker1.example.com.pem -extfile extfile.cnfConfigure the daemon to use TLS (Ubuntu)
On the Docker host, create a new directory called /etc/docker/ssl,
and put the following files in there:
- ca.pem
- docker1.example.com.key
- docker1.example.com.pem
Edit /etc/default/docker, and add the following parameters to DOCKER_OPTS
DOCKER_OPTS="--tlsverify --tlscacert=/etc/docker/ssl/ca.pem --tlscert=/etc/docker/ssl/docker1.example.com.pem --tlskey=/etc/docker/ssl/docker1.example.com.key -H=0.0.0.0:2376"Then restart the docker service:
service docker restartCreate a client key-pair:
Generate a client key and csr:
openssl genrsa -out client.key 4096
openssl req -subj '/CN=client' -new -key client.key -out client.csr
echo extendedKeyUsage = clientAuth > extfile.cnfSign the client CSR with your CA
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem -extfile extfile.cnfConnect:
docker --tlsverify --tlscacert=ca.pem --tlscert=client.pem --tlskey=client.key -H=docker1.example.com:2376 versionAutomatically connect using TLS
You can create a ~/.docker directory on your client machine, and copy certificates there
following a strict filename convention:
mkdir -pv ~/.docker
cp ca.pem ~/.docker/ca.pem
cp client.pem ~/.docker/cert.pem
cp client.key ~/.docker/key.pemThen set the DOCKER_HOST and DOCKER_TLS_VERIFY environment variables:
export DOCKER_HOST=tcp://docker1.example.com:2376 DOCKER_TLS_VERIFY=1You can now simply run:
docker version