Wednesday, November 13, 2019
The Secrets of Docker Secrets
Most web apps need login information of some kind, and it is a bad idea to put them in your source code where it gets saved to a git repository that everyone can see. Usually these are handled by environment variables, but Docker has come up with what they call Docker secrets. The idea is deceptively simple in retrospect. While you figure it out it is arcane and difficult to parse what is going on.
Essentially the secrets function create in memory files in the docker image that contain the secret data. The data can come from files, or a Docker swarm.
The first thing to know is that the application running in the docker image needs to be written to take advantage of the Docker secrets function. Instead of getting the password from an environment variable, it would get the password from the file system at /run/secrets/secretname. Not all images available use this functionality. If they don't describe how to use Docker secrets, the won't work. The files will be created in the image, but the application won't read them.
For a development setup having files outside of the git source tree works well. To create a file with a secret, I created a folder called serverdata, with a dev/ and prod/ folder within. In the dev/ folder, run this command with all the secret data you will need:
Function and description. I have some configuration details as well.
Using Secrets with docker-compose
This is the docker-compose.yml that builds a mongodb image with all the configuration.
Of course it gets more complicated. I wanted to watch the changes in the database within my node application for various purposes. This function is only supported in a replicated set in Mongo. To fully automate the configuration and initialization of Mongo within Docker images using replication requires a second Docker image that waits for the Mongo images to initialize, then runs a script. So here is the complete docker-compose.yml for setting up the images:
replicate.js
This sets up mongoDb with admin user and password, as well as a user that is used from the node.js apps for reading and writing data.
No passwords in my git repository, and an initialized database. This is working for my development setup, with a mongo database, replicated so that I can get change streams, and read and write function from the node.js application.
More to come.
Essentially the secrets function create in memory files in the docker image that contain the secret data. The data can come from files, or a Docker swarm.
The first thing to know is that the application running in the docker image needs to be written to take advantage of the Docker secrets function. Instead of getting the password from an environment variable, it would get the password from the file system at /run/secrets/secretname. Not all images available use this functionality. If they don't describe how to use Docker secrets, the won't work. The files will be created in the image, but the application won't read them.
For a development setup having files outside of the git source tree works well. To create a file with a secret, I created a folder called serverdata, with a dev/ and prod/ folder within. In the dev/ folder, run this command with all the secret data you will need:
The names simply need to tell you what they do. What the secret is called in the image is set in the docker configuration. This is what my dev/ folder looks like:echo "shh, this is a secret" > mysecret.txt
-rw-r--r-- 1 derek derek 66 Nov 5 14:49 mongodb_docker_path
-rw-r--r-- 1 derek derek 6 Oct 22 14:09 mongodb_rootusername
-rw-r--r-- 1 derek derek 13 Oct 22 14:08 mongodb_rootuserpwd
-rw-r--r-- 1 derek derek 18 Oct 22 14:10 mongodb_username
-rw-r--r-- 1 derek derek 14 Oct 22 14:10 mongodb_userpwd
-rw-r--r-- 1 derek derek 73 Oct 22 14:02 oauth2_clientid
-rw-r--r-- 1 derek derek 25 Oct 22 14:02 oauth2_clientsecret
-rw-r--r-- 1 derek derek 14 Oct 22 14:03 oauth2_cookiename
-rw-r--r-- 1 derek derek 25 Oct 22 14:04 oauth2_cookiesecret
-rw-r--r-- 1 derek derek 33 Oct 26 08:27 oauth2_redirecturl
Function and description. I have some configuration details as well.
Using Secrets with docker-compose
This is the docker-compose.yml that builds a mongodb image with all the configuration.
version: '3.6'services: mongo-replicator: build: ./mongo-replicator container_name: mongo-replicator secrets: - mongodb_rootusername - mongodb_rootuserpwd - mongodb_username - mongodb_userpwd environment: MONGO_INITDB_ROOT_USERNAME_FILE: /run/secrets/mongodb_rootusername MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongodb_rootuserpwd MONGO_INITDB_DATABASE: admin networks: - mongo-cluster depends_on: - mongo-primary - mongo-secondary
And the secrets are defined as follows:
The secrets: section reads the contents of the file into a namespace, which is the name of the /run/secrets/filename. Mongo docker image looks for an environment variable with the suffix _FILE, then reads the secret from that file in the image file system. Those are the only two variables supported by the Mongo image.secrets: mongodb_rootusername: file: ../../serverdata/dev/mongodb_rootusername mongodb_rootuserpwd: file: ../../serverdata/dev/mongodb_rootuserpwd mongodb_username: file: ../../serverdata/dev/mongodb_username mongodb_userpwd: file: ../../serverdata/dev/mongodb_userpwd mongodb_path: file: ../../serverdata/dev/mongodb_docker_path
Of course it gets more complicated. I wanted to watch the changes in the database within my node application for various purposes. This function is only supported in a replicated set in Mongo. To fully automate the configuration and initialization of Mongo within Docker images using replication requires a second Docker image that waits for the Mongo images to initialize, then runs a script. So here is the complete docker-compose.yml for setting up the images:
The Dockerfile for the mongo-replicator looks like this:version: '3.6'services: mongo-replicator: build: ./mongo-replicator container_name: mongo-replicator secrets: - mongodb_rootusername - mongodb_rootuserpwd - mongodb_username - mongodb_userpwd environment: MONGO_INITDB_ROOT_USERNAME_FILE: /run/secrets/mongodb_rootusername MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongodb_rootuserpwd MONGO_INITDB_DATABASE: admin networks: - mongo-cluster depends_on: - mongo-primary - mongo-secondary mongo-primary: container_name: mongo-primary image: mongo:latest command: --replSet rs0 --bind_ip_all environment: MONGO_INITDB_DATABASE: admin ports: - "27019:27017" networks: - mongo-cluster mongo-secondary: container_name: mongo-secondary image: mongo:latest command: --replSet rs0 --bind_ip_all ports: - "27018:27017" networks: - mongo-cluster depends_on: - mongo-primary
Mongo with various scripts added to it. Here they are.FROM mongo:latest ADD ./replicate.js /replicate.js ADD ./seed.js /seed.js ADD ./setup.sh /setup.sh CMD ["/setup.sh"]
replicate.js
seed.jsrs.initiate( { _id : "rs0", members: [ { _id: 0, host: "mongo-primary:27017" }, { _id: 1, host: "mongo-secondary:27017" }, ] });
and finally what does all the work, setup.shdb.users.updateOne( { email: "myemail@address.com"}, { $set: { email: "myemail@address.com", name: "My Name"} }, { upsert: true },);
In the docker-compose.yml the depends_on: orders the creation of images, so this one waits until the others are done. It runs the replication.js which initializes the replication set, then waits for a while. The password and username are read from the /run/secrets/ file, the linefeed removed, then the user is created in the mongo database. Then seed.js is called to add more initial data#!/usr/bin/env sh if [ -f /replicated.txt ]; then echo "Mongo is already set up"else echo "Setting up mongo replication and seeding initial data..." # Wait for few seconds until the mongo server is up sleep 10 mongo mongo-primary:27017 replicate.js echo "Replication done..." # Wait for few seconds until replication takes effect sleep 40 MONGO_USERNAME=`cat /run/secrets/mongodb_username|tr -d '\n'` MONGO_USERPWD=`cat /run/secrets/mongodb_userpwd|tr -d '\n'` mongo mongo-primary:27017/triggers <<EOFrs.slaveOk()use triggersdb.createUser({ user: "$MONGO_USERNAME" , pwd: "$MONGO_USERPWD", roles: [ { role: "dbOwner", db: "admin" }, { role: "readAnyDatabase", db: "admin" }, { role: 'readWrite', db: 'admin'}]}) EOF mongo mongo-primary:27017/triggers seed.js echo "Seeding done..." touch /replicated.txt fi
This sets up mongoDb with admin user and password, as well as a user that is used from the node.js apps for reading and writing data.
No passwords in my git repository, and an initialized database. This is working for my development setup, with a mongo database, replicated so that I can get change streams, and read and write function from the node.js application.
More to come.
- Using secrets in node.js applications and oauth2_proxy
- The oauth2_proxy configuration
- Nginx configuration to tie the whole mess together
Comments:
<< Home
Thanks for such a great post. This post gives lot of information.
Docker and Kubernetes Training
Docker and Kubernetes Online Training
Docker and Kubernetes Training in Hyderabad
Kubernetes Online Training
Docker Online Training
Docker Training in Hyderabad
Kubernetes Training in Hyderabad
Docker and Kubernetes Training
Docker and Kubernetes Online Training
Docker and Kubernetes Training in Hyderabad
Kubernetes Online Training
Docker Online Training
Docker Training in Hyderabad
Kubernetes Training in Hyderabad
There are lots of information about latest software analyzing huge amounts of unstructured data in a distributed computing environment.This information seems to be more unique and interesting.Thanks for sharing.
PHP Training in Chennai | Certification | Online Training Course | Machine Learning Training in Chennai | Certification | Online Training Course | iOT Training in Chennai | Certification | Online Training Course | Blockchain Training in Chennai | Certification | Online Training Course | Open Stack Training in Chennai |
Certification | Online Training Course
Post a Comment
PHP Training in Chennai | Certification | Online Training Course | Machine Learning Training in Chennai | Certification | Online Training Course | iOT Training in Chennai | Certification | Online Training Course | Blockchain Training in Chennai | Certification | Online Training Course | Open Stack Training in Chennai |
Certification | Online Training Course
Subscribe to Post Comments [Atom]
<< Home
Subscribe to Posts [Atom]