Day 09:Docker Swarm Secrets: Securely Manage Sensitive Data (Part 2)

Day 09:Docker Swarm Secrets: Securely Manage Sensitive Data (Part 2)

Introduction

This repository complements Part 1 of the Docker Swarm series, focusing on securely managing sensitive data such as database credentials, API keys, and more. By leveraging Docker Swarm secrets, you can separate sensitive information from your container images, enhancing the security posture of your applications.

Understanding Docker Swarm Secrets

Docker Swarm secrets allow you to store sensitive information outside of container images, preventing accidental exposure or unauthorized access. Secrets are managed as key-value pairs and can be referenced securely within your containers.

Prerequisites

Create 1 master node and 2 worker nodes and connect master worker nodes using docker swarm

create IAM user with administrator access role attached and create access and secret keys

Creating Secrets

Here are two common methods to create Docker Swarm secrets:

1. File-Based Secrets

  1. Create a file containing your sensitive data. For example, create a file named credentials and store your access keys and secret keys within it.

     [default]
    
     aws_access_key_id=AAAAAAAAAAAAAAAAAA
    
     aws_secret_access_key=ASASASASASASASA
    

  2. Convert the file into a secret using the following command:

     docker secret create <secret_name> <file_path>
    

    Replace <secret_name> with a descriptive name (e.g., aws_creds) and <file_path> with the file path (e.g., .credentials).

2. Environment Variable Secrets

  1. Define environment variables during container creation to provide secrets directly:

     docker run -e <environment_variable_name>=<secret_value> <image_name>
    

    Replace <environment_variable_name> with a variable name (e.g., DB_PASSWORD) and <secret_value> with your actual password.

Mounting Secrets

Once you've created your secret, you can mount it within your containers for secure access.

  1. Create a aws-cli.yml file defining your service configuration:

     version: '3.3'
     services:
       cli:
         image: imkiran13/notes-app:latest
         secrets:
           - source: aws_creds
             target: /root/.aws/credentials
             uid: '1000'
             gid: '1000'
             mode: 0700
         deploy:
           replicas: 1
           placement:
             constraints: [node.role != manager]
           resources:
             reservations:
               memory: 128M
             limits:
              memory: 512M
         environment:
           AWS_DEFAULT_REGION: us-east-1
         networks:
           - appnet
     secrets:
       aws_creds:
         external: true
     networks:
       appnet:
    
  2. Deploy the service:

     docker stack deploy -c aws-cli.yml AWS_CLI
    

Verifying Secrets

  1. Use docker service ps to check the status of your deployed service

  2. Security Caution: Connect to a worker node (not the manager) to enhance security

    install aws cli once you enter into docker container

  3. Verify access using commands like env, aws s3 ls, and aws describe-vpc | jq

    Delete resources

Security Best Practices

  • Always use strong passwords and access keys.

  • Regularly rotate secrets.

  • Consider tools like Vault or AWS Secrets Manager for advanced secret management.

Example: Using Secrets in MySQL

Create secrets and deploy a MySQL service using Docker Swarm:

1️⃣ Create an Overlay Network for Swarm

docker network create --driver overlay appnet


2️⃣ Create Docker Secrets for MySQL Passwords

openssl rand -base64 12 | docker secret create db_root_password -
openssl rand -base64 12 | docker secret create db_dba_password -

✅ These commands generate random passwords and store them as Docker secrets.


3️⃣ Create a db.yml File

Create a Docker Swarm stack file (e.g., db.yml) with MySQL using secrets:

version: '3.3'

services:
  db:
    image: mysql:8.0
    secrets:
      - db_root_password
      - db_dba_password
      - source: db_root_password
        target: ROOT_PASSWORD
      - source: db_dba_password
        target: DB_PASSWORD
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      resources:
        reservations:
          memory: 128M
          cpus: '0.25'
        limits:
         memory: 512M
         cpus: '1'
    ports:
      - 3306:3306
    environment:
      MYSQL_USER: dba
      MYSQL_DATABASE: mydb
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
      MYSQL_PASSWORD_FILE: /run/secrets/db_dba_password
    networks:
      - appnet
    volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
        - "datavol:/var/lib/mysql"

  adminer:
    image: adminer
    ports:
      - 8888:8080
    networks:
      - appnet

  utils:
    image: imkiran13/notes-app:latest
    deploy:
      replicas: 1
      placement:
        constraints: [node.role != manager]
    networks:
      - appnet

secrets:
  db_root_password:
    external: true
  db_dba_password:
    external: true

networks:
  appnet:
    external: true
  saikiran:
  sai:

volumes:
  datavol:

📌 Important Notes:

  • Secrets are mounted as files in /run/secrets/, not directly as environment variables.

  • You must use _FILE suffix (e.g., MYSQL_ROOT_PASSWORD_FILE) to read from the secrets file.


4️⃣ Deploy the Stack

docker stack deploy -c db.yml DB

Go to the master node, copy the public IP, and access port 8888.

Retrieve the password for root user

Now you are logged In

✅ This deploys the MySQL service inside Docker Swarm.


5️⃣ Install MySQL Client & Connect

Verify on which node app is running and go inside that node

To access MySQL from a worker/manager node:

docker exec -it DB_utils.1.2d1nfgz0g5t8bqs8ittehjoui bash
apt-get update && apt-get install -y default-mysql-client

Now, connect to MySQL inside Swarm:

mysql -h DB -u root -p

When prompted, use the password stored in the db_root_password secret.


🛑 Remove the Stack

If you need to stop and remove everything:

docker stack rm my_stack
docker secret rm db_root_password db_dba_password
docker network rm appnet