Docker secrets
Here are two approaches to handle passwords, keys, etc in docker compose files.
1. Docker secrets using external files (easier)
In this example you can store your sensitive data in external files.
Original file containing a secret token:
version: "3.9"
services:
duckdns:
image: linuxserver/duckdns:latest
container_name: duckdns
environment:
- TZ=Europe/Madrid
- SUBDOMAINS=mydomain1.duckdns.org,mydomain2.duckdns.org
- TOKEN=mysecrettokenexample
restart: unless-stopped
networks:
net_rp:
New file without my sensitive data. You will need to store mysecrettokenexample
into the file duckdns_token.key
.
version: "3.9"
services:
duckdns:
image: linuxserver/duckdns:latest
container_name: duckdns
environment:
- TZ=Europe/Madrid
- SUBDOMAINS=mydomain1.duckdns.org,mydomain2.duckdns.org
- TOKEN=/run/secrets/duckdns_token
restart: unless-stopped
secrets:
- duckdns_token
secrets:
duckdns_token:
file: ./duckdns_token.key
networks:
net_rp:
2. Docker secrets (standard)
Here instead you store your sensitive data in docker secrets.
1 - Check if Swarm is enabled (it is disabled by default).
$ docker info | grep Swarm
Swarm: inactive
2 - If it’s disabled, enable it with:
docker swarm init
3 - Let’s create our first secret tagged myfirstkey
:
printf mysecretpassword | docker secret create myfirstkey -
You can also create a random password easily with:
openssl rand -base64 16 | docker secret create secure-key -
You can also use the password that is stored in a file:
docker secret create secure-key myfile.key
4 - You can verify your secret is created with:
docker secret ls
5 - Once the secret is created, you need to create a service that gives you access to that secret. For example:
$ docker service create --name redis_for_duckdns --secret="duckdns_token" redis:alpine
txof7ceq2kwxmn0cfkvvjvpu7
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
All containers in this service will be able to access the secret.
6 - You can verify the service is created with
~$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
txof7ceq2kwx redis_for_duckdns replicated 1/1 redis:alpine
7 - Deploy a stack.
$ docker stack deploy --compose-file docker-compose.yml redis_for_duckdns
8 - In this case the secret is no longer stored in an external file so we can remove file: ./duckdns_token.key
from the docker-compose file:
version: "3.9"
services:
duckdns:
image: linuxserver/duckdns:latest
container_name: duckdns
environment:
- TZ=Europe/Madrid
- SUBDOMAINS=mydomain1.duckdns.org,mydomain2.duckdns.org
- TOKEN=/run/secrets/duckdns_token
restart: unless-stopped
secrets:
- duckdns_token
secrets:
duckdns_token:
networks:
net_rp:
3. Also good to know
How to remove a secret
You can remove a secret with docker secret rm
but if its in use by a service you will get the following error:
$ docker secret rm myfirstkey
Error response from daemon: rpc error: code = InvalidArgument desc = secret 'myfirstkey' is in use by the following service: redis
This is because you first need to remove the secret from the service that’s using it:
$ docker service update --secret-rm myfirstkey redis
redis
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
Then if you wish you can remove the secret and the service:
$ docker secret rm myfirstkey
myfirstkey
$ docker service rm redis
Check what secrets are in a specific service
$ docker ps --filter name=redis
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b9be8e5af67 redis:alpine "docker-entrypoint.s…" 6 hours ago Up 6 hours 6379/tcp redis.1.glnjn4p3y03re7aupgf9wcaw5
$ docker ps --filter name=redis -q
5b9be8e5af67
$ docker container exec $(docker ps --filter name=redis -q) ls -l /run/secrets
total 4
-r--r--r-- 1 root root 4 Oct 24 13:58 myfirstkey
Check that a container has access to a secret
$ docker container exec $(docker ps --filter name=redis -q) cat /run/secrets/myfirstkey
hola