Skip to main content

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:

  1. Docker installed (version 1.13.0 or higher)
  2. A Docker Swarm initialized (run docker swarm init if you haven't already)
  3. 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

bash
echo "MySuperSecretPassword123!" > password.txt
docker secret create db_password password.txt
rm password.txt # Remove the file after creating the secret

From standard input

bash
echo "MySuperSecretPassword123!" | docker secret create db_password -

Checking created secrets

To list all secrets in the Swarm:

bash
docker secret ls

Output:

ID                          NAME          CREATED             UPDATED
ov7aohqvvot0gzgc11v5ov7a4 db_password About a minute ago About a minute ago

To inspect a specific secret:

bash
docker secret inspect db_password

Output:

json
[
{
"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:

bash
docker secret rm db_password

Using Secrets in Docker Services

Using Secrets with docker service create

To create a service that uses a secret:

bash
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 named db_password at /run/secrets/db_password in the container
  • --secret source=db_user,target=my_user: Mounts the secret named db_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:

yaml
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 Swarm
  • file: ./db_user.txt specifies that Docker Compose should create the secret from the specified file when deploying the stack

To deploy the stack:

bash
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

bash
#!/bin/bash
PASSWORD=$(cat /run/secrets/db_password)
echo "Connecting to database with password: $PASSWORD"

Node.js

javascript
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

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

bash
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

yaml
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

bash
docker stack deploy -c docker-compose.yml mywebapp

Step 4: Verify the deployment

bash
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

  1. Don't store secrets in your code repository: Keep secrets out of your codebase and create them as part of your deployment process.

  2. Rotate secrets regularly: Update your secrets periodically for enhanced security.

  3. Use descriptive names: Name your secrets in a way that clearly indicates their purpose.

  4. Limit access to secrets: Only provide secrets to services that actually need them.

  5. Keep your Swarm secure: Since secrets are stored in the Swarm's internal database, securing your Swarm managers is critical.

  6. Clean up unused secrets: Remove secrets that are no longer needed using docker secret rm.

  7. Use proper file permissions: When using secrets in containers, set appropriate file permissions to restrict access.

Limitations of Docker Swarm Secrets

  1. Only for Swarm mode: Secrets are only available in Docker Swarm mode, not for standalone containers.

  2. Read-only: Secrets are mounted as read-only files in containers.

  3. No secret updates: To update a secret, you need to create a new one and update the service to use it.

  4. 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

  1. Create a Docker Swarm Secret for an API key and use it in a simple web service.
  2. Set up a multi-container application using Docker Compose with database credentials stored as secrets.
  3. Create a script that automatically rotates Docker Secrets and updates the associated services.
  4. 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! :)