Docker Compose Secrets is a powerful tool that can help you secure sensitive data. By using Compose Secrets, you can easily keep your data safe and protected from unauthorized access. To use Docker Compose Secrets, you first need to create a new compose file. In this example, we will use the docker-compose up command to create a new compose file called secrets.yml.

cat secrets.yml # # This is a simple secrets file that stores our docker-compose secrets in # an easily accessible location. The secrets are accessible via the # “docker-compose” command line tool and the “docker-compose exec” # command line interface. The secret files are stored in the same directory as the # docker-compose files. $GOPATH /usr/local $HOME /docker-compose $SUBDIR /docker-compose/secrets 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212


Safe secret management is an important aspect of container security. If you’re injecting passwords and API keys as environment variables, you risk unintentional information exposure. Shell variables are often logged, passed down to child processes, or leaked to error reporting services without your knowledge.

Injecting values as dedicated secrets mitigates these risks. Docker has built-in support for secure secret management which you can hook into with Docker Compose. Access to secrets is granted on a per-service basis.

How Do Secrets Work?

The Docker CLI has a batch of secret management commands but these only work with Swarm clusters. You can’t add secrets to standalone containers using the Docker CLI alone.

Docker Compose added “fake” secrets to bring these capabilities to workloads without a cluster. Compose’s implementation functions similarly to the Docker Swarm features and works with any Compose file.

Secrets are created as regular text files which are bind mounted into your containers. Your application accesses the secret’s value by reading the file’s contents. This model lets values stay inert until they’re explicitly used within your container, unlike permanently visible environment variables.

Defining Secrets in Compose Files

Getting a secret into a container is a two-step process. First you need to define the secret, using the top-level secrets field in your Compose file. Then you update your service definitions to reference the secrets they require.

Here’s an example that uses secrets to safely supply a password to a service:

The secret’s value will be read from your working directory’s db_password.txt file when you run docker-compose up. Compose will mount the file to /run/secrets/db_password within the container. Your app can access the database password by reading the contents of the secret file.

Using Existing Docker Secrets

Beyond file-based secrets, Compose also lets you reference existing Docker Swarm secrets. If you use this mechanism, you must create the secrets in Docker before you run docker-compose up. The docker secrets command space will only work when your active Docker endpoint is a Swarm manager node.

Create the secret using the Docker CLI:

Now update your Docker Compose file to reference the secret:

Setting the secret’s external field instructs Compose to source its value from your existing Docker secrets. The stack will fail with an error if you try to start it before the secret exists.

Extended Secret Syntax

Compose supports a longer secrets syntax if you need more granular control over the injection process. Switching to this syntax lets you customize file permissions and change the secret’s mounted name.

Five optional fields are available:

source – The name of the secret to reference – this must be one of the values defined in your Compose file’s secrets section. target – Filename to use when the secret is mounted into the container. uid – UID to set on the mounted secret file. Defaults to 0. gid – GID to set on the mounted secret file. Defaults to 0. mode – Filesystem permissions to apply to the mounted secret file, expressed in octal notation. This defaults to 0444. Beware that secret files are never writable as they’re always mounted into a container’s temporary filesystem.

Here’s a modified example which renames the mounted secret file and changes its permissions:

The simple syntax is usually sufficient for most deployments. If you’ve got more specific requirements, the extended version should give you the control you need. Individual secret references can mix and match the two syntaxes within the same Compose file.

Secrets and Image Authorship

Many popular community Docker images now support secrets instead of environment variables. As an image author, offering secrets is a best practice approach to protecting your users’ data.

You can support both mechanisms by allowing environment variables to be set to a file path. If your image needs a database connection, let users set the DB_PASSWORD environment variable to either P@55w0rd or /run/secrets/db_password. Your container should check whether the variable’s value references a valid file; if it does, discard it and read the final value out of the file.

This model gives users the flexibility to choose the most appropriate mechanism for their deployment. Remember that not all users will be able to adopt secrets – if Swarm and Compose are both unavailable, they’ll have no way of supplying their values.

Conclusion

Using secrets instead of regular environment variables reduces the risks of unintentional information disclosure. Imagine a worst case scenario where a container sent its environment variables to a compromised third-party logging service. Attackers now have your database password and API keys.

By restricting secret data to filesystem access, values can’t be inadvertently read as they’re not a perpetual feature of your environment. Remember that secret files carry their own risks though. You may be tempted to commit them into source control, which would mean anyone with access to your repository could read their values.

Secrets should be “secret” throughout your container’s lifecycle. For production deployments, it’s usually best to automate builds with a CI system. Set your secrets in your CI provider’s pipeline settings, then use your build script to write them out to files which Compose can access. This ensures only you have access to the actual values, via your CI tool’s interface.