Use Docker secrets to avoid saving sensitive credentials within your image or passing them directly on the command line.

Source: https://docs.docker.com/engine/swarm/secrets/#about-secrets




Basic Redis example

1) Create a secret #origin

echo "mysecret1b1ee244779d3b7a90bc80be3721fac5f26b350480680" | docker secret create SECRET_POSTGRES_ROOT -;

2) RM a secret #origin

docker secret rm SECRET_POSTGRES_ROOT -;

3) Create a demo container #origin

docker service  create --name="redis" --secret="SECRET_POSTGRES_ROOT" redis:alpine;

4a) Find the container ID #on_node

docker ps --filter name=redis -q;

4b) Ensure that 'SECRET_POSTGRES_ROOT' is available #on_node

docker exec $(docker ps --filter name=redis -q) ls -l /run/secrets;

4c) Show value for 'SECRET_POSTGRES_ROOT' #on_node

docker exec $(docker ps --filter name=redis -q) cat /run/secrets/SECRET_POSTGRES_ROOT;

5) Remove a secret #origin

docker service update --secret-rm="SECRET_POSTGRES_ROOT" redis

Ensure it's removed

See Step 4c

6) Add secret to an existing container #origin

docker service update --secret-add="SECRET_POSTGRES_ROOT" redis;

Ensure it's available

See Step 4c

7) Clean up stuff from this demo

docker service rm redis mysql;
docker secret rm SECRET_POSTGRES_ROOT;

Wordpress and Mysql example

Create a random password #origin

openssl rand -base64 20 | docker secret create mysql_password -;
openssl rand -base64 20 | docker secret create mysql_root_password -;
docker secret ls;

Create network #origin

docker network create -d overlay mysql_private;

Create mysql service

docker service create \
 --name mysql \
 --replicas 1 \
 --network mysql_private \
 --mount type=volume,source=mysql-data,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" \

docker service ls;
docker service ps mysql;

Create wordpress service

docker service create \
     --name wordpress \
     --replicas 1 \
     --network mysql_private \
     --publish 80:80 \
     --mount type=volume,source=wpdata,destination=/var/www/html \
     --secret source=mysql_password,target=wp_db_password,mode=0400 \
     -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" \

/// mode - specifies that the secret is not group-or-world-readable, by setting the mode to 0400.

docker service ls;
docker service ps wordpress;

Log on the wordpress site

Rotate a secretΒΆ

Create a 2ND random password #origin

openssl rand -base64 44 | docker secret create mysql_password_v2 -;
docker secret ls;

See what is the password we just created

docker service create --name="checkthis" --secret="mysql_password_v2" alpine sleep 20;
echo; sleep 3;
docker exec $(docker ps --filter name=checkthis -q) cat /run/secrets/mysql_password_v2;
echo; sleep 3;
docker service rm checkthis; echo;

Update the MySQL service

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 is restarting

docker service ls;
docker service ps mysql;

/// Even though the MySQL service has access to both the old and new secrets now, the MySQL password for the WordPress user has not yet been changed.

Update MySQL password for the wordpress user using the mysqladmin

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

Update the wordpress service to use the new password

docker service update \
--secret-rm mysql_password \
--secret-add source=mysql_password_v2,target=wp_db_password,mode=0400 \

/// wordpress is restarting

docker service ls;
docker service ps wordpress;

/// Verify that WordPress works by browsing to http://localhost:30000/ on any swarm node again

Revoke access to the old secret from the MySQL service and remove the old secret from Docker.

docker service update \
--secret-rm mysql_password \

docker secret rm mysql_password;

Clean up stuff from this demo

docker service rm wordpress mysql;

docker volume rm mydata wpdata;

docker secret rm mysql_password_v2 mysql_root_password;

/// That was easy!

See ya soon!
Pascal Andy |Β Twitter

P.S. If you have solid skills πŸ€“ with Docker Swarm, Linux and the things mention here and you would love πŸ’š to help a startup to launch πŸ”₯ a solid project, I would love to get to know you 🍻. Buzz me πŸ‘‹ on Twitter @askpascalandy. You can see the things that are done and the things we have to do here.