Docker Swarm Secrets
Introduction
When deploying applications in a containerized environment, one of the most challenging aspects is managing sensitive information such as API keys, passwords, and certificates. Exposing these credentials in your Dockerfile or docker-compose files is a significant security risk. Docker Swarm, Docker's native orchestration tool, provides a solution to this problem through Docker Secrets.
Docker Secrets allows you to securely store, manage, and distribute sensitive data to only the containers that need access to it. In this guide, we'll explore how Docker Swarm Secrets work, how to create and manage them, and how to use them effectively in your applications.
What are Docker Swarm Secrets?
Docker Secrets is a feature in Docker Swarm that lets you manage sensitive data and securely provide it to only those containers that need access to it. Some key characteristics of Secrets:
- Secrets are encrypted at rest when stored in the Swarm
- Secrets are encrypted during transit when being sent to containers
- Secrets are mounted as in-memory filesystems inside containers (/run/secrets)
- Secrets are only accessible to services that have been granted explicit access
- Secrets are scoped to a specific Swarm cluster
Prerequisites
Before you begin with Docker Swarm Secrets, make sure you have:
- Docker installed (version 1.13.0 or higher)
- A Docker Swarm initialized (run
docker swarm init
if you haven't already) - Basic understanding of Docker and Docker Swarm concepts
Creating and Managing Secrets
Creating a Secret
You can create a secret in Docker Swarm in several ways:
From a file
echo "MySuperSecretPassword123!" > password.txt
docker secret create db_password password.txt
rm password.txt # Remove the file after creating the secret
From standard input
echo "MySuperSecretPassword123!" | docker secret create db_password -
Checking created secrets
To list all secrets in the Swarm:
docker secret ls
Output:
ID NAME CREATED UPDATED
ov7aohqvvot0gzgc11v5ov7a4 db_password About a minute ago About a minute ago
To inspect a specific secret:
docker secret inspect db_password
Output:
[
{
"ID": "ov7aohqvvot0gzgc11v5ov7a4",
"Version": {
"Index": 17
},
"CreatedAt": "2023-07-06T15:12:34.123456789Z",
"UpdatedAt": "2023-07-06T15:12:34.123456789Z",
"Spec": {
"Name": "db_password",
"Labels": {}
}
}
]
Removing a Secret
To remove a secret:
docker secret rm db_password
Using Secrets in Docker Services
Using Secrets with docker service create
To create a service that uses a secret:
docker service create \
--name db \
--secret db_password \
--secret source=db_user,target=my_user \
mysql:latest
In this example:
--secret db_password
: Mounts the secret nameddb_password
at/run/secrets/db_password
in the container--secret source=db_user,target=my_user
: Mounts the secret nameddb_user
at/run/secrets/my_user
in the container
Using Secrets with Docker Compose
To use secrets with Docker Compose, you need to use version 3.1 or higher of the Compose file format:
version: '3.1'
services:
db:
image: mysql:latest
secrets:
- db_password
- source: db_user
target: my_user
uid: '103'
gid: '103'
mode: 0440
secrets:
db_password:
external: true
db_user:
file: ./db_user.txt
In this example:
external: true
indicates that the secret has already been created in Docker Swarmfile: ./db_user.txt
specifies that Docker Compose should create the secret from the specified file when deploying the stack
To deploy the stack:
docker stack deploy -c docker-compose.yml myapp
Accessing Secrets in Containers
Once a secret is mounted in a container, it's available as a file in the /run/secrets/
directory. Here's how you might access it in different languages:
Bash Script
#!/bin/bash
PASSWORD=$(cat /run/secrets/db_password)
echo "Connecting to database with password: $PASSWORD"
Node.js
const fs = require('fs');
// Read the secret
const password = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();
console.log(`Connecting to database with password: ${password}`);
Python
# Read the secret
with open('/run/secrets/db_password', 'r') as f:
password = f.read().strip()
print(f"Connecting to database with password: {password}")
Real-World Example: Secure Database Credentials
Let's walk through a complete example of setting up a web application with a database using Docker Swarm Secrets.
Step 1: Create the necessary secrets
echo "root" | docker secret create db_user -
echo "MySuperSecretPassword123!" | docker secret create db_password -
echo "webdb" | docker secret create db_name -
Step 2: Create a Docker Compose file
version: '3.1'
services:
web:
image: nginx:alpine
ports:
- "80:80"
secrets:
- db_user
- db_password
- db_name
depends_on:
- db
deploy:
replicas: 2
db:
image: mysql:latest
secrets:
- source: db_root_password
target: mysql_root_password
- source: db_password
target: mysql_password
- source: db_name
target: mysql_database
- source: db_user
target: mysql_user
environment:
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password
- MYSQL_PASSWORD_FILE=/run/secrets/mysql_password
- MYSQL_DATABASE_FILE=/run/secrets/mysql_database
- MYSQL_USER_FILE=/run/secrets/mysql_user
volumes:
- db_data:/var/lib/mysql
deploy:
placement:
constraints:
- node.role == manager
secrets:
db_user:
external: true
db_password:
external: true
db_name:
external: true
db_root_password:
external: true
volumes:
db_data:
Step 3: Deploy the stack
docker stack deploy -c docker-compose.yml mywebapp
Step 4: Verify the deployment
docker stack ps mywebapp
Output:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
q2bpmr2yx0wi mywebapp_db.1 mysql:latest node1 Running Running 2 minutes ago
xd93p0n7wpvp mywebapp_web.1 nginx:alpine node2 Running Running 2 minutes ago
lw0s5j9328n5 mywebapp_web.2 nginx:alpine node3 Running Running 2 minutes ago
Best Practices for Docker Swarm Secrets
-
Don't store secrets in your code repository: Keep secrets out of your codebase and create them as part of your deployment process.
-
Rotate secrets regularly: Update your secrets periodically for enhanced security.
-
Use descriptive names: Name your secrets in a way that clearly indicates their purpose.
-
Limit access to secrets: Only provide secrets to services that actually need them.
-
Keep your Swarm secure: Since secrets are stored in the Swarm's internal database, securing your Swarm managers is critical.
-
Clean up unused secrets: Remove secrets that are no longer needed using
docker secret rm
. -
Use proper file permissions: When using secrets in containers, set appropriate file permissions to restrict access.
Limitations of Docker Swarm Secrets
-
Only for Swarm mode: Secrets are only available in Docker Swarm mode, not for standalone containers.
-
Read-only: Secrets are mounted as read-only files in containers.
-
No secret updates: To update a secret, you need to create a new one and update the service to use it.
-
Limited to containers: Secrets can only be used within containers, not by external applications.
Summary
Docker Swarm Secrets provide a secure way to manage sensitive data in a containerized environment. By encrypting secrets at rest and in transit and mounting them as in-memory filesystems inside containers, Docker ensures that your sensitive information remains protected.
In this guide, we've covered:
- What Docker Swarm Secrets are and how they work
- How to create, manage, and use secrets in your Docker Swarm services
- How to access secrets within containers
- A real-world example of using secrets for database credentials
- Best practices and limitations of Docker Swarm Secrets
By following these best practices and understanding the limitations, you can effectively use Docker Swarm Secrets to enhance the security of your containerized applications.
Additional Resources
Exercises
- Create a Docker Swarm Secret for an API key and use it in a simple web service.
- Set up a multi-container application using Docker Compose with database credentials stored as secrets.
- Create a script that automatically rotates Docker Secrets and updates the associated services.
- Compare Docker Swarm Secrets with other secret management tools like HashiCorp Vault or AWS Secrets Manager.
If you spot any mistakes on this website, please let me know at feedback@compilenrun.com. I’d greatly appreciate your feedback! :)