Securing Docker engine with TLS.
Introduction
By default, when you install and start Docker on Linux, Docker-Client (cli) access Docker-Engine on local host with unix socket
. Docker-Engine allows any process to access api from local host. Yes, that’s right Docker-Engine is nothing more than small web server exposing REST API with root access to Linux kernel functionality (cgroups, kernel namespaces, etc.). In this post I will show how to access Docker-Engine over network (tcp) and how to secure this communication using TLS ( client / server certificates ).
What is TLS ?
The TLS protocol allows client-server applications to communicate across a network in a way designed to prevent eavesdropping and tampering (3).
Steps :
- Generate CA (authority) certificates.
- Generate Server side certs.
- Generate Client side certs.
- Configure Docker-Engine to listen on tcp and respect TLS.
- Test Docker-Client using newly generated certs.
Generate CA (authority) certificates.
We need CA certs to sign client and server side certs. On Docker-Engine server execute :
This will produce : ca-key.pem
and ca.pem
files. We will store certs in user home ~/.docker/
please ensure this folder exists make -p ~/.docker/
. Also ensure openssl
package is installed on your server : yum install openssl
.
Generate Server side certs.
Server side certs will be used by Docker-engine daemon. Lets start by generating key cert.:
Next we need to generate request to sign cert. Because its important to know certificate subject (server DNS, IP, etc. ) we will use subjectAltName
which will give us flexibility to set multiple subject names. Lets create openssl
config file :
nano ~/.docker/openssl.cnf
Its important to replace IP.1
with your real server IP where Docker-Engine will run. With second line (IP.2
) we allow to use certs in connections from local host (for debug purposes).
Now lets generate request itself :
And sign server cert with CA cert + CA key and sign request :
In the end we are interested to have 3 cert files on Docker-Engine server :
cert.pem
- Server certificatekey.pem
- Server key fileca.pem
- CA certificate.
Generate Client side certs.
Before generating certs on Docker-client side please ensure you copy CA certs and CA key file ( ~/.docker/ca.pem
, ~/.docker/ca-key.pem
) to client instance . Also ensure openssl
is installed.
Same way as with server first generate key file :
Next create openssl config file :
nano ~/.docker/openssl.cnf
And create certificate sign file
Last step is to sign client certificate :
In the end on client machine we have following files :
cert.pem
- Client certificate.key.pem
- Client key file.ca.pem
- CA certificate.
Configure Docker-Engine to listen on tcp and respect TLS.
Now when certs are ready lets switch back to instance with Docker-Engine. We need to instruct Docker-Engine daemon to listen on tcp
port 2376
and verify TLS cert. Docker daemon configuration depends on docker version, for example in docker 1.9.0
we can set config in /etc/sysconfig/docker
file :
sudo nano /etc/sysconfig/docker
Please notice sentence -H unix:///var/run/docker.sock
, by this we will allow to make socket connections from local host. Last thing, restart daemon :
And check docker logs for any error message:
Test Docker-Client using newly generated certs.
Last piece, we need to test can we reach Docker-Engine from Docker-Client. Lets switch back to client instance and instruct Docker-client (CLI) to use remote Docker-Engine:
Lets ask Docker-Engine to return server version :
As we can see client and server versions are different. We can simplify process of typing same commands over and over by setting env. variables.