29 May 2024 · Software Engineering

    Three Practical Use Cases of Docker Secrets

    10 min read
    Contents

    As discussed in the previous article, Docker secrets are a secure way to manage sensitive information in Dockerized environments. You got to see how you could incorporate secrets into compose files and also how you could manage secrets using the docker secret command.

    As a follow-up to the previous article, we’ll be looking at three practical use cases of Docker secrets. We’ll go through how to use Docker secrets in a Dockerfile, manage WordPress secrets with Docker secrets, and roll back a secret. Through these practical examples, you will better understand how you can use Docker secrets in real-world scenarios.

    Prerequisites

    To fully understand the hands-on examples in this article, you should have a basic understanding of Docker and Docker secrets. If you’re new to Docker secrets, you can check out the previous article to get started.

    Additionally, you should have Docker installed on your machine preferably with Docker Swarm enabled.

    Using Docker Secrets in a Dockerfile

    In some cases, you might need to incorporate secrets directly into your Docker image. This could be necessary when you need to build an image that requires a secret to be present at build time. In this example, we’ll look at incorporating a secret into a Docker image using a Dockerfile.

    Step 1: Create a Secret

    First, you must create a secret that will be incorporated into the Docker image. You can create a secret using the docker secret createcommand.

    For this tutorial, let’s say you have an AWS access key stored in a file named aws_credentials in your home directory ($HOME/.aws/credentials).

    Step 2: Create a Dockerfile

    Create a Dockerfile in your project directory. This Dockerfile will define the steps needed to build your Docker image, including how to access and use the secret.

    FROM your_base_image
    
    # Create a directory for the secret
    RUN mkdir -p /run/secrets
    
    # Copy the secret file into the container
    COPY $HOME/.aws/credentials /run/secrets/aws_credentials
    
    # Use the secret in your build process
    RUN --mount=type=secret,id=mytoken \
        TOKEN=$(cat /run/secrets/aws_credentials) \
        # Your build commands here

    Replace your_base_image with the base image you’re using for your Docker image.

    This Dockerfile creates a directory for the secret, copies the secret file into the container, and then uses the secret in the build process. The --mount=type=secret,id=mytoken flag allows you to pass the secret to the build process securely.

    In an actual scenario, you would replace the # Your build commands here with the specific commands needed to build your Docker image.

    NOTE: As emphasized in the previous article, sharing secrets over version control systems like Git is not recommended. For this example, we’re assuming the secret file is stored locally on your machine, so it’s not shared with others.

    Step 3: Build Your Docker Image

    Now, build your Docker image using the docker build command. Make sure to use the --secret flag to pass the secret to the build process.

    docker build --secret id=mytoken .

    This command will build your Docker image while securely passing the secret to the build process.

    Step 4: Use the Secret in Your Application

    You can now use the secret in your application as needed. For example, if you’re using the AWS access key in your application to interact with AWS services, you can access it using the TOKEN environment variable set in the Dockerfile.

    NOTE: Remember to replace mytoken with a meaningful identifier for your secret. Also, ensure that the secret file (aws_credentials in this example) is stored securely and is only accessible to authorized users.

    Managing WordPress Secrets

    WordPress is a popular content management system that often requires sensitive information like database passwords to be securely managed.

    In this example, we’ll create single-node MySQL and WordPress services using Docker secrets to manage sensitive credentials. We’ll set up a MySQL database for WordPress and configure WordPress to connect to MySQL.

    Overview

    This tutorial can get a bit complex, so let’s break it down into steps:

    1. Generate random alphanumeric passwords for MySQL root and WordPress database.
    2. Create Docker secrets for MySQL and WordPress.
    3. Set up a MySQL service with Docker secrets.
    4. Configure a WordPress service to use MySQL with Docker secrets.
    5. Verify the services are running and test WordPress functionality.

    Step 1: Generate Docker Secrets

    Generate random passwords for MySQL root and WordPress database:

    # Generate MySQL root password
    openssl rand -base64 20 | docker secret create mysql_root_password -
    
    # Generate WordPress database password
    openssl rand -base64 20 | docker secret create mysql_password -

    You should now have two Docker secrets with an output similar to:

    uxm1a4sjjsg7enq2m1dtmvnon
    5judi7jm6d02xs99lj8061wul

    Step 2: Create MySQL Service

    Create a MySQL service with Docker secrets:

    docker network create -d overlay mysql_private
    
    docker service create \
        --name mysql \
        --replicas 1 \
        --network mysql_private \
        --mount type=volume,source=mydata,destination=/var/lib/mysql \
        --secret source=mysql_root_password,target=mysql_root_password \
        --secret source=mysql_password,target=mysql_password \
        -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \
        -e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \
        -e MYSQL_USER="wordpress" \
        -e MYSQL_DATABASE="wordpress" \
        mysql:latest

    Your output should look similar to:

    v87xhur2iqhwhvmql11345l7k
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 

    This command creates a MySQL service with the specified secrets and environment variables. The MySQL service will be connected to the mysql_private overlay network.

    Step 3: Create WordPress Service

    Create a WordPress service that connects to MySQL using Docker secrets:

    docker service create \
        --name wordpress \
        --replicas 1 \
        --network mysql_private \
        --publish published=30000,target=80 \
        --mount type=volume,source=wpdata,destination=/var/www/html \
        --secret source=mysql_password,target=wp_db_password \
        -e WORDPRESS_DB_USER="wordpress" \
        -e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password" \
        -e WORDPRESS_DB_HOST="mysql:3306" \
        -e WORDPRESS_DB_NAME="wordpress" \
        wordpress:latest

    You should see output similar to:

    whoumrpbcry3exply4fl9euue
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 

    This command creates a WordPress service that connects to the MySQL service using Docker secrets. The WordPress service will be accessible on port 30000.

    Step 4: Verify and Test

    Finally, verify that the services are running and test WordPress functionality:

    # Verify services
    docker service ls
    
    # Test WordPress
    docker service ps wordpress

    You output should look similar to:

    ID             NAME          IMAGE              NODE             DESIRED STATE   CURRENT STATE           ERROR     PORTS
    q2qzd1d2hup1   wordpress.1   wordpress:latest   docker-desktop   Running         Running 2 minutes ago             

    Access http://localhost:30000/ from any swarm node to set up WordPress using the web-based wizard. Verify that WordPress is operational and its state is saved across service restarts.

    Figure 1: WordPress Installation Page

    NOTE: You need an active Docker Swarm to run the services. If you’re using Docker Desktop, you can enable Swarm mode by running docker swarm init.

    Rotating Back a Secret

    Rotating a secret means changing its value without affecting the services that use it. This is an important security practice to prevent unauthorized access to sensitive information.

    This tutorial will demonstrate how to rotate a secret in Docker, building upon the previous use case. We’ll create a new secret with a new MySQL password, update the MySQL and WordPress services to use it, and then remove the old secret.

    Step 1: Create a New Secret

    Generate a new password and store it as a secret named mysql_password_v2:

    openssl rand -base64 20 | docker secret create mysql_password_v2 -
    
    vwqvnkm1gploicqk2g32vwpf2

    Step 2: Update Services

    Update the MySQL service to grant it access to the old and new secrets. Remove the old secret and add the new one:

    docker service update \
        --secret-rm mysql_password mysql
    
    docker service update \
        --secret-add source=mysql_password,target=old_mysql_password \
        --secret-add source=mysql_password_v2,target=mysql_password \
        mysql

    You should see output similar to:

    mysql
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Waiting 5 seconds to verify that tasks are stable... 
    service update paused: update paused due to failure or early termination of task f98yfogvf606ddrdc0z3b1paf
    
    mysql
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 

    This command updates the MySQL service to use the new secret while keeping the old secret for backward compatibility.

    Step 3: Change MySQL Password

    Change the MySQL password for the WordPress user using the mysqladmin CLI. This command reads the old and new passwords from the secret files:

    docker container exec $(docker ps --filter name=mysql -q) \
        bash -c 'mysqladmin --user=wordpress --password="$(< /run/secrets/old_mysql_password)" password "$(< /run/secrets/mysql_password)"'

    You should see output similar to:

    mysqladmin: [Warning] Using a password on the command line interface can be insecure.
    Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.

    This command changes the MySQL password for the WordPress user to the new password.

    Step 4: Update WordPress Service

    Update the WordPress service to use the new password. Trigger a rolling restart of the service:

    docker service update \
        --secret-rm mysql_password \
        --secret-add source=mysql_password_v2,target=wp_db_password \
        wordpress
    You should see output similar to:
    
    ```bash
    wordpress
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 
    ```
    
    This command updates the WordPress service to use the new secret and removes the old secret.
    

    Step 5: Verify Functionality

    On the WordPress site, verify that you can still access and interact with the site as expected. Ensure that the MySQL password change did not affect the WordPress functionality.

    NOTE: You might be wondering how all this can work in CI/CD pipelines such as Semaphore. To make this possible, you’ll need scripts. So, instead of manually running these commands on your machine, the CI/CD pipeline will execute this script and commands automatically whenever there is a new code push or a trigger event. To try it out, check out this GitHub repository that goes through this process.

    However, Semaphore has a much simpler way of including secrets into your project. You can check this page on creating and managing secrets to know more.

    Step 6: Revoke Access and Cleanup

    After verifying that the services are operational, revoke access to the old secret and clean up the old secret:

    docker service update \
        --secret-rm mysql_password \
        mysql
    
    docker secret rm mysql_password
    You should see output similar to:
    
    ```bash
    mysql
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged 
    mysql_password
    ```
    

    Conclusion

    In this article, we looked at three practical use cases of Docker secrets. We explored how to incorporate secrets into a Docker image using a Dockerfile, manage WordPress secrets using Docker secrets, and rotate a secret in Docker.

    With these examples, using secrets in various scenarios becomes more straightforward. You can now apply Docker secrets to your projects to securely manage sensitive information and improve the security of your Dockerized applications.

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Avatar
    Writen by:
    As a mentor at AltSchool Africa, Prince Onyeanuna combines his passion for cloud engineering and education to support the learning and development of aspiring cloud engineers. He leverages his expertise in DevOps and technical writing to provide guidance, feedback, and resources to the students, helping them master cloud technologies and best practices.
    Avatar
    Reviewed by:
    I picked up most of my soft/hardware troubleshooting skills in the US Army. A decade of Java development drove me to operations, scaling infrastructure to cope with the thundering herd. Engineering coach and CTO of Teleclinic.