The Definitive Cheatsheet for Docker Secrets
Goal
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
#hashtag:
/ origin: RUN FROM ON NODE MANAGER
/ on_node: RUN FROM ON NODE WHERE THE SERVICE WAS DEPLOYED
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" \
mysql:latest;
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" \
wordpress:latest;
/// 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
127.0.0.1:80
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;
/// 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;
/// 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 \
mysql;
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.