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 initif 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 named- db_passwordat- /run/secrets/db_passwordin the container
- --secret source=db_user,target=my_user: Mounts the secret named- db_userat- /run/secrets/my_userin 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: trueindicates that the secret has already been created in Docker Swarm
- file: ./db_user.txtspecifies 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.
💡 Found a typo or mistake? Click "Edit this page" to suggest a correction. Your feedback is greatly appreciated!