Knowledge for the World

Getting started with Docker secrets

Docker secrets is a secrets management tool designed for use with Docker Swarm. And of course, Docker Swarm refers to the cluster management and orchestration features built into the Docker Engine. So imagine you've got a few services that you want to distribute across various nodes - Docker Swarm makes this unbelievably simple.

Now, if you care about security (even a little bit) you'll soon be looking for a way to get your sensitive data (think database passwords, API credentials, et al.) out of your code base. We certainly don't want to store a configuration file with all of our passwords on our Github repository and hope for the best. While there are various ways to deal with this problem, Docker again provides a simple solution - Docker secrets. This guide will walk you through various aspects of setting up a using Docker secrets.

1

Before we dive in, let's discuss how this works at a high level. As mentioned previously, Docker secrets is only available to swarm services. So first we add a secret to the swarm, and then we give our services access to the secrets they require. When the service is created (or updated), the secret is then mounted onto the container in the /run/secrets directory. Now your application has access to the secrets it requires.

I wrote a neat guide on running a Docker Swarm on the Raspberry Pi in case you find it interesting. :)

2

With a swarm already running, you can use the docker secret create command to add a new secret to the swarm.

Here is a basic example:

echo "mydatabasepassword" | docker secret create db_pass -

Now let's use the docker secret ls command to confirm that our secret was added:

docker secret ls

should output something like this:

ID                          NAME                CREATED             UPDATED
0inh8z8zprse1qjapuvl00b68   db_pass             1 min ago           1 min ago

3

Now that you've added the secret to the swarm, you need to give the service access. This can be accomplished when the service is created or updated.

Here's an example of how to add a secret when the service is created:

docker service create --secret db_pass --name secret-test alpine ping howchoo.com

In this example, I'm adding the db_pass secret we created in the previous step to a service running the alpine image.

If we've already got a service running and we want to add (or change) a secret, you can use the --secret-add option.

docker service update --secret-add db_pass running_service_name

4

At this point, accessing your secret is as simple as reading from a file. In the example above, our secret named mydatabasepassword is mounted at /run/secrets/mydatabasepassword and it contains a single password.

Depending on how you organize your secrets, it might make sense to write a utility function that fetches the secrets for you. In Python, that could look something like this:

def get_secret(secret_name):
    try:
        with open('/run/secrets/{0}'.format(secret_name), 'r') as secret_file:
            return secret_file.read()
    except IOError:
        return None

database_password = get_secret('db_pass')

5

There are a few different ways to use this in practice, and based on the needs of your application you can choose the way that works best for you.

A secret per password

In the example above, I showed how you would store a single password in a secret. This might be appropriate if you're not managing too many secrets. In this case, you would manually create each secret and add them each to the appropriate service when it is created or updated.

There are some things to consider with this method. If you've got a lot of secrets, there's room for manual error and it can be time consuming.

A secret per service

So another possible method might be to store all of the secrets that each service requires in a single file - perhaps a json file called "my_service.json". Now you're adding a single secret file per service, and all of the passwords are stored in a file that can be quickly read in by your application.

This provides a much cleaner and quicker way to configure the secrets, plus it simplifies things in the application layer as well. But the obvious downside is that services will often share secrets, so some of your sensitive data might be duplicated.