Dockerfile secrets best practices and usage

Kenny DuMez
Kenny DuMez
Graphite software engineer

Managing secrets securely within Dockerfiles helps to maintain the security and integrity of your applications. Secrets can include passwords, API keys, SSL certificates, and other sensitive data essential for your application's functionality but hazardous if exposed. This guide explores the best practices for handling Dockerfile secrets, providing detailed examples to demonstrate effective strategies.

Directly placing secrets in Dockerfiles or source code is highly discouraged because:

  • Dockerfiles can be easily inspected by anyone with access to the image.
  • Secrets can inadvertently be checked into source control, leading to potential security breaches.

One common method to manage secrets is to pass them at runtime using environment variables. While this method doesn't store secrets in the Docker image, it still requires secure handling to prevent leakage via logs or server misconfigurations.

Terminal
FROM node:14
WORKDIR /app
COPY . .
CMD ["node", "app.js"]

You can run the container with the environment variable like so:

Terminal
docker run -e API_KEY='your_secret_api_key' myapp

Docker secrets are a secure way to manage sensitive data and are designed to be safe and easy to use, especially in swarm mode. Secrets are stored outside of the project's image and filesystem, only accessible to the services that need them.

  1. Create a secret:

    Terminal
    echo "your_secret_data" | docker secret create my_secret -
  2. Modify your service to use the secret:

    Terminal
    version: '3.1'
    services:
    app:
    image: myapp
    secrets:
    - my_secret
    secrets:
    my_secret:
    external: true
  3. Access the secret within your application:

    Secrets in Docker are mounted into the container’s filesystem at /run/secrets/<secret_name>. Your application needs to read from this location to use the secret.

Docker's BuildKit offers a way to use secrets during the build process without leaving a trace in the final image. This is particularly useful for needing access to private repositories or API keys during the build.

  1. Enable BuildKit by setting the environment variable:

    Terminal
    export DOCKER_BUILDKIT=1
  2. Define a Dockerfile with a secret:

    Terminal
    ## syntax=docker/dockerfile:1.0.0-experimental
    FROM alpine
    RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
  3. Build the image, providing the secret:

    Terminal
    docker build --secret id=mysecret,src=mysecret.txt .

Here, mysecret.txt should contain the secret data, and the id=mysecret matches the ID specified in the Dockerfile.

Managing secrets in Docker involves avoiding common pitfalls like embedding them in Dockerfiles or source code. Instead, utilize Docker's built-in features like environment variables, Docker secrets, or BuildKit for secure handling. Each method has its appropriate use case, and choosing the right one depends on the specific security requirements and operational context of your application. Regularly review and audit how secrets are managed in your Docker environments to ensure they remain secure.

For further reading on managing secrets in Docker, see the official Docker documentation.

Git inspired
Graphite's CLI and VS Code extension make working with Git effortless.
Learn more

Graphite
Git stacked on GitHub

Stacked pull requests are easier to read, easier to write, and easier to manage.
Teams that stack ship better software, faster.

Or install our CLI.
Product Screenshot 1
Product Screenshot 2