Give Codeship’s CI/CD Platform a Try

Want to learn more?

I’m sure we’ve all been there. That moment when you realize that important and sensitive access details have leaked online into a public space and potentially rendered your services to unrequited access. With the ever-growing amount of services we depend on for our development stack, the number of sensitive details to remember and track has also increased. To cope with this problem, tools have emerged in the field of “secrets management.” In this post, I am going to look at Docker Secrets, the new secrets management feature available in Docker 1.13 and higher.

The feature doesn’t require much work on your part from a Docker perspective, but you may need to refactor your applications to take advantage of it. I will present ideas on how to do this, but not exhaustively.

Swarm Only

Docker Secrets only work across Docker swarms, mostly because that’s the area where secrets management makes the most sense. After all, Swarm is aimed at production usage where multiple Docker instances need to share access details between themselves. If you want to use secrets management in a standalone container, you need to run a container with a scale value set to ‘1’. Docker for Mac and Windows doesn’t support multinode swarm mode, but you can use them to create a multinode swarm with Docker Machine.

Getting Secrets

As you create secrets from the command line, you have the whole gamut of tools available to you to for creating random passwords and piping output. For example, to create a random password for a database user:

openssl rand -base64 20 | docker secret create mariadb_password -

This will return an ID for the secret.

You need to issue this command a second time to generate a password for the MariaDB root user. You will need this to get started, but you won’t need this for every service.

If you’re already forgetting the secrets you’ve created, then the time-honored ls command also works here:

docker secret ls

Exchanging Secrets

To keep the secrets, well, secret, communication between the services happens in an overlay network that you define. They’re only available in that overlay network by calling their ID.

docker network create -d overlay mariadb_private

This will also return an ID for that network. Again you can use docker network ls to remind yourself of what’s available.

Create Service(s)

This example will have a Docker node running MariaDB, and a node running Python. In a final application, the Python application would read and write to the database.

First, add a MariaDB service. This service uses the network you created to communicate, and the secrets created earlier are saved into two files: one for the root password and one for a default user password. Then pass all the variables you need to the service as environment variables.

The Python instance again uses the private network you created and copies the secrets accessible in the network. A better (production-ready) option would be to create the databases your application needs in an admin program and never give the application access to root passwords, but this is purely for an example.

The example above uses a simple Docker image I created that sets up packages for creating a web application using Flask for serving web pages and PyMySQL for database access. The code doesn’t do much but shows how you could access the environment variables from the Docker container.

For example, to connect to the database server with no database specified:

Rotating Secrets

It’s good practice to frequently change sensitive information. However, as you likely know, updating those details in applications is a dull process most would rather avoid. Via Services, Docker Secrets management allows you to change the values without having to change your code.

Spread the Word

Docker Secrets is a new feature, but Docker encourages image maintainers to add support for it as soon as possible for better security among Docker users. This entails allowing for a similar process to the example above, where a container can read every parameter it needs from a file(s) created by generating a secret instead of hard-coded into an application. This enforces the idea of containerized applications as containers can come and go, but always have access to the important information you need for your application to run.

For more details on the secret command (there’s not much!), read the reference guide here.

Subscribe via Email

Over 60,000 people from companies like Netflix, Apple, Spotify and O'Reilly are reading our articles. Subscribe to receive a weekly newsletter with articles around Continuous Integration, Docker, and software development best practices.

We promise that we won't spam you. You can unsubscribe any time.

Join the Discussion

Leave us some comments on what you think about this topic or if you like to add something.