While building a container, I need to pass a token into the build process. The container build step needs to download a package using said secret token - and that token is part of the URL. The token will show up on the screen, and potentially in any logfile. Not good.
Note: This applies to docker compose (and docker buildx).
The step in the Dockerfile looks like this:
| |
And shows up in the build output on the screen, and in the log:
| |
To make matters worde, the token - in the current build process - is passed in as commandline parameter:
| |
This too shows up in the build log:
| |
And potentially in the process list of the host.
It is easy to copy and paste the build output, and forget about sanitizing the secret tokens. Let’s improve this entire process.
Secrets
Docker has the capability to manage secrets for the build process.
This will mount the defined secret as a file under /run/secrets/, which then can be accessed using standard commandline tools.
compose.yaml
The compose.yaml needs two entries, first the secrets section:
| |
This example defines the token secret, and the content is provided from the environment variable $TOKEN.
Secrets can be read from a file, using the file method. Or from the environment, using the environment method. The environment variable name does not have to match the secret name.
In the services section, the service itself also gets a secrets subsection:
| |
This will mount the token secret into the process for the myservice. By specifying the secrets in the service definition, one can select which secrets are available for which service. Not every service needs to see every secret.
In this example, I need the secrets during build, therefore the secrets section is a subsection of build. If you need the secrets during runtime, the secrets section is a subsection of myservice. If you need both, possibly with different secrets, define both subsections.
Dockerfile
As mentioned before, each secret is mounted under /run/secrets/. In the example above, the token secret is /run/secrets/token. The RUN command in the Dockerfile has a --mount option:
| |
Let’s see if that works:
| |
That works. By the way, the build output is made visible using the --progress plain option.
URL handling
Now that we have hidden the secrets, and found a way to securely pass the token into the build process, there is however still the problem with the URL with the token shown in the build output. This problem can be solved by creating a script and run the script, instead of running the curl command directly.
| |
The -s option silences curl, otherwise the URL might appear again. Now run the script:
| |
The +x option for bash is the same as setting set +x in the script: it disables tracing of the executed commands.
To show that this step does not print the URL at all, here’s the script run with the - invalid - URL, which will fail. After all, downloads.website.secret is a made up website name.
| |
No URL shown in the output, not even when there is an error. No accidental copy of credentials. Good.
Summary
Docker secrets are a secure way to pass sensitive data from files or from the environment into the build process or the running container.
This avoids accidentally exposing credentials to the viewer, or copy and paste sensitive information.
Comments
With an account on the Fediverse or Mastodon, you can respond to this post. Known replies are displayed below:
Note: This will load data from mastodon.social.
Learn how this is implemented here.
Share: