How to use Docker build secrets: Securely pass sensitive data in builds

Docker build secrets are a Docker BuildKit feature that securely passes sensitive data, such as API keys and passwords, during image builds without baking them into the final image.
Keep reading as we walk you through everything you need to know about using build secrets:
- What Docker build secrets are and why they’re essential.
- How to create, pass, and consume secrets in a Dockerfile.
- How to integrate build secrets with Docker Compose for multi-service applications.
- How to use SSH mounts for secure access to private resources.
- Best practices for keeping your secrets safe.
By the end, you’ll be able to protect sensitive data at build time using ephemeral secret management techniques that are secure, temporary, and designed for modern container workflows.
Download free docker cheat sheet
What are Docker build secrets?
Docker build secrets provide a secure way to use sensitive files during a Docker build without leaving them in the final image.
When you use a secret, Docker temporarily mounts it into the build container. Once the build step using the secret finishes, Docker unmounts the file. The secret is not stored in any image layers or its history.
The main advantage over older methods like ARG and ENV is security. Data passed with ARG or ENV can be inspected using the docker history command, which could expose your secrets.
With build secrets, the data is ephemeral and never becomes part of the image, preventing accidental leaks.
What are the types of build secrets?
Docker supports two types of mounts for handling sensitive data during builds:
- Secret mounts. Used for general-purpose secrets, such as API keys, database passwords, or configuration files. Docker limits these secret files to 500 KB.
- SSH mounts. Designed to forward SSH agent connections, allowing secure access to private Git repositories or other SSH-protected resources during the build.
How to create and pass Docker build secrets
The detailed steps to create and pass your first build secret are below.
1. Install Docker and enable Docker BuildKit
First, install Docker on your system. The steps vary depending on your operating system. For this example, we’ll use Docker on Ubuntu.
Next, enable Docker BuildKit, as it powers the build secrets feature. You can enable it for a single build or permanently.
If you want to enable BuildKit for a single build, run the build command with the DOCKER_BUILDKIT=1 environment variable:
DOCKER_BUILDKIT=1 docker build .
To enable BuildKit permanently, edit the Docker daemon configuration file at ~/.docker/config.json and add the following feature flag:
{ "features": { "buildkit": true } }
2. Create your secret file
A secret file is a plain text file that contains the sensitive data you want to protect. For this example, create a file to store a database password.
In your terminal, create the secret file:
echo "mydb_password" > mydb-password.txt
If you have multiple secrets, store each one in a separate file. This lets you manage their permissions and mount them individually into the container. For instance:
echo "my_api_key" > api-key.txt echo "my_ssh_key" > ssh-key.txt
3. Pass the secret with the –secret flag
To pass the secret file into the build process, use the –secret flag in your docker build command like this:
--secret id=mydb_password,src=mydb-password.txt
Here’s a breakdown of the flag’s syntax:
- –secret. The flag that tells BuildKit you’re passing a secret.
- id=mydb_password. A unique identifier for the secret. Use this ID to reference the secret inside your Dockerfile.
- src=mydb-password.txt. The path to the secret file on your host machine.
You’ll use this flag later after referencing the secret in your Dockerfile.
Consuming secrets in Dockerfiles
Once you pass a secret to the build command, you can make it available inside your Dockerfile.
1. Reference your secret in your Dockerfile
To use a secret, mount it within a RUN instruction using the –mount flag. The mount type for secrets is type=secret.
Here’s an example Dockerfile that mounts your database password secret:
# Use Ubuntu base image FROM ubuntu:24.04 # Mount a secret and check if it’s there, but don’t print the secret value RUN --mount=type=secret,id=mydb_password \ ls -l /run/secrets/ && \ echo "Secret is available and correctly mounted!" || echo "No secret found"
In this example, id=mydb_password corresponds to the ID you specified in the –secret flag. By default, Docker mounts the secret at /run/secrets/, and the filename inside the container is the secret’s ID.
2. Build your image
Now, build the image using the complete command, including the –secret flag. Add –no-cache and –progress=plain to view the output clearly.
docker build --no-cache --progress=plain --secret id=mydb_password,src=mydb-password.txt -t my-image .
If successful, the output will show that the secret mounted correctly inside the /run/secrets/ directory during that RUN step.
Once the step finishes, the secret disappears and is not saved in the final image.
3. Access secrets within build steps
You can access the content of the secret file like any other file. For example, use the cat command to view its contents during the build for debugging.
Update your Dockerfile as follows:
# Mount a secret and access its content RUN --mount=type=secret,id=mydb_password \ cat /run/secrets/mydb_password || echo "No secret found"
Then, run the build again:
docker build --no-cache --progress=plain --secret id=mydb_password,src=mydb-password.txt -t my-image .
This will print the secret’s content to the console. While this is useful for testing, be careful not to leave this in your production Dockerfiles, as it can expose secrets in your build logs.
If you’re building multi-service apps, the next step is integrating secrets into Docker Compose.
Integrating build secrets in Docker Compose
Docker Compose is a tool for defining and running multi-container Docker apps. You can also manage build secrets directly within your docker-compose.yml file, simplifying the management of configurations for complex services.
This approach is ideal for managing apps like a Kafka cluster on Docker, where multiple components need secure configurations.
To use build secrets with Docker Compose, define them in the top-level secrets section of your docker-compose.yml file and then assign them to the relevant services.
Here’s an example using a PostgreSQL database service:
version: "3.8" services: db: image: postgres environment: POSTGRES_PASSWORD_FILE: /run/secrets/mydb_password secrets: - mydb_password secrets: mydb_password: file: ./mydb-password.txt
In this file:
- The top-level secrets key defines a secret named mydb_password and tells Compose to source it from the ./mydb-password.txt file.
- The db service references this secret, making it available inside the container.
- The POSTGRES_PASSWORD_FILE environment variable tells the PostgreSQL image to read the database password from the specified file path inside the container, which is /run/secrets/mydb_password by default.
To start your app, run docker-compose up. Compose will read the secret file from your host and securely mount it into the running container without exposing it in the service definition.
Please note that while Docker Compose works well for managing app secrets like passwords, you’ll often need to handle authentication secrets. That’s where SSH mounts help.
Using SSH mounts for secure access
SSH mounts are a specialized type of build secret that forward SSH keys. They are useful when you need to clone a private Git repository or access other SSH-protected resources during a build.
Like regular secrets, the SSH key is only available temporarily during the RUN step and never gets baked into the final image.
In automated CI/CD pipelines, where you might use tools like Ansible to install and configure Docker, SSH mounts provide a secure channel for these build steps.
To use an SSH mount, load your SSH key into your local SSH agent.
First, start the SSH agent if it isn’t already running:
eval $(ssh-agent)
Then, add your private key to the agent:
ssh-add ~/.ssh/id_rsa
Verify that the key is loaded:
ssh-add -l
Next, reference the SSH mount in your Dockerfile. The mount type for SSH is type=ssh.
Below is an example that clones a private Git repository:
FROM ubuntu:24.04 # Install Git and SSH dependencies RUN apt update && apt install -y git ssh-client # Add GitHub's SSH key to known_hosts to avoid host verification prompts RUN mkdir -p -m 0700 ~/.ssh && \ ssh-keyscan github.com >> ~/.ssh/known_hosts # Clone a private Git repository using the mounted SSH key RUN --mount=type=ssh git clone git@github.com:your-org/your-private-repo.git /myproject
Finally, build the image using the –ssh flag. This flag tells Docker to forward the SSH agent socket to the build:
docker build --ssh default -t my-image .
Now that you know how to handle both file-based secrets with Docker Compose and SSH keys with SSH mounts, let’s look at best practices to keep your builds secure.
What are some best practices for managing Docker build secrets?
Following best practices helps protect sensitive data in Docker containers throughout the development lifecycle. Some universal guidelines are listed below:
- Never use ARG or ENV for sensitive data. These instructions make values visible through the docker history command and let attackers extract them from image layers. Always use –secret or –ssh mounts instead.
- Use separate secrets for each environment. Avoid sharing credentials between development, staging, and production. This limits the impact if a secret from one environment is compromised.
- Exclude secrets from version control. Add secret files and directories to your .gitignore file to prevent them from being committed to your repository.
- Use CI/CD build-time secret management. Platforms like GitHub Actions or Jenkins provide secure ways to inject secrets at build time. Use these features instead of storing secrets in your repository.
- Rotate secrets regularly. Change passwords, API keys, and other credentials on a schedule. Use automation tools like HashiCorp Vault to manage this process efficiently.
- Audit your Dockerfiles often. Review Dockerfiles for insecure practices, such as hardcoded credentials or ENV instructions with sensitive data, that may have been added by mistake.
Key takeaways
Using Docker build secrets is an essential practice for securing containerized applications. It prevents sensitive data like API keys, tokens, and credentials from being accidentally exposed in your final Docker images.
Here are the main points you must remember:
- Always use BuildKit’s secret management. Use the –secret flag for files and the –ssh flag for SSH keys to mount sensitive data temporarily during the build.
- Never hardcode secrets. Avoid using ARG or ENV instructions for sensitive data, since they are insecure and easily exposed.
- Integrate secrets into your workflows. Use Docker Compose’s secrets feature to manage configurations for multi-container apps cleanly and securely.
- Maintain strong security hygiene. Keep secret files out of version control with .gitignore, rotate secrets regularly, and use separate credentials for each environment.
Next, strengthen your Docker security by setting up a private Docker registry to control image access and protect sensitive workloads.
This approach safeguards images, reduces the risk of unauthorized access, and gives you full control over your deployment pipeline.
All of the tutorial content on this website is subject to Hostinger's rigorous editorial standards and values.