Configuring Docker Remote API with TLS on CoreOS
I recently set up a CoreOS box for futzing around and wanted to use it as a replacement for my qemu-kvm workflow (amongst other things). Typically this involves spinning up various distros of linux to compile software, provide services, or do demos on. They're typically ephemeral in that I frequently tear them down when I'm done and the workspace is configured automatically using some setup scripts. Before I'd done this with virsh behind a rather restrictive vpn, but this box is a little more exposed and I wanted some kind of auth in front. Luckily, docker 0.10.0 provides TLS authentication for its remote tcp API. Perfect.
I'm going to assume you already have a working coreos and docker instance somwhere. After that, we're going to merge a couple of tutorials from the docker side for https auth and the coreos side for configuring the remote api. But we're not going to use the docker-tcp.socket example as I was unable to get that to work with the docker cert options.
Docker uses client/server certificates to grant access. So we need to create some private/public key pairs and a CA serial file. The example below creates one with a 10 year expiration.
#!/bin/bash set -ex mkdir certs && cd certs echo "Creating server keys..." echo 01 > ca.srl openssl genrsa -des3 -out ca-key.pem openssl req -new -x509 -days 3650 -key ca-key.pem -out ca.pem openssl genrsa -des3 -out server-key.pem openssl req -new -key server-key.pem -out server.csr openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem \ -out server-cert.pem echo "Creating client keys..." openssl genrsa -des3 -out client-key.pem openssl req -new -key client-key.pem -out client.csr echo extendedKeyUsage = clientAuth > extfile.cnf openssl x509 -req -days 365 -in client.csr -CA ca.pem -CAkey ca-key.pem \ -out client-cert.pem -extfile extfile.cnf echo "Stripping passwords from keys..." openssl rsa -in server-key.pem -out server-key.pem openssl rsa -in client-key.pem -out client-key.pem
After being asked a bunch of annoying questions, you'll need to copy the generated client certificates from your server to your client or vice versa if you created the certs on your client.
Make sure you use the correct FQDN (or '*' to match all servers) of the server for the server certificate. We don't have a fully working dns for our lab network, so I just made sure I had a /etc/hosts entry on my client.
We need to tweak the default docker.service definition in CoreOS to use the TLS certs we created. This should be done as root. The below script assumes the server certificates are in working directory of the script.
#!/bin/bash set -ex systemctl stop docker systemctl disable docker echo "Copying scripts to /var/ssl/" mkdir -p /var/ssl cp ca.pem server-cert.pem server-key.pem /var/ssl/ cat<<-EOF > /etc/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.io [Service] ExecStartPre=/bin/mount --make-rprivate / # Run docker but don't have docker automatically restart # containers. This is a job for systemd and unit files. ExecStart=/usr/bin/docker -d -s=btrfs -r=false --tlsverify --tlscacert=/var/ssl/ca.pem --tlscert=/var/ssl/server-cert.pem --tlskey=/var/ssl/server-key.pem -H fd:// -H 0.0.0.0:4243 #ExecStart=/usr/bin/docker -d -s=btrfs -r=false -H fd:// [Install] WantedBy=multi-user.target EOF systemctl enable /etc/systemd/system/docker.service systemctl start docker
Setting Up Your Client
Coy the client certificates to a good location, I put mine in ~/.docker/. Also, for convenience, set the DOCKER_HOST environment variable.
mkdir ~/.docker cp ca.pem ~/.docker cp client-cert.pem ~/.docker/cert.pem cp client-key.pem ~/.docker/key.pem export DOCKER_HOST=<docker service fqdn>:4243
If you named the files exactly like above, you should be able to access your TLS protected docker api with with the following command from your client.
docker --tlsverify images