Docker Secret

Thursday, Mar 20, 2025| Tags: Docker

DISCLAIMER: Image is generated using FREE version of ChatGPT.




Dockeri Secret


1. Setup

2. Hard Wired Secrets

3. Environment Variables

4. Env File

5. Swarm Mode


Setup


Before we do anything, let’s make sure we have the foundation setup properly.

If you don’t have docker and docker-compose installed, please follow the steps below. Otherwise, proceed to the next section.


$ sudo apt update

$ sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Add your user to the docker group to avoid the need to use sudo for every docker command:


$ sudo usermod -aG docker $USER

Check the installation:


$ docker --version
Docker version 28.0.1, build 068a01e

Now install the docker-compose:


$ sudo apt install -y docker-compose

OR


$ sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose

$ sudo chmod +x /usr/local/bin/docker-compose

Verify the docker-compose installation:


$ docker-compose --version
docker-compose version 1.29.2, build unknown

I am going to create an alias for docker ps in the ~/.bashrc file so that the output is well-formatted.


alias dps='docker ps --format "Container ID: {{.ID}}\nImage: {{.Image}}\nCommand: {{.Command}}\nCreated: {{.CreatedAt}}\nStatus: {{.Status}}\nPorts: {{.Ports}}\nNames: {{.Names}}\n"'

For the demo, I am going to use the latest MongoDB image.

In this post, I will explore the following options:


1. Hard wired secrets
2. Use of environment variables
3. Use of --env-file flag
4. Secret in swarm mode

Hard Wired Secrets


Well, in this case, we save the secrets in the configuration, though it’s not a good idea.

Here is the configuration file, docker-compose-open.yml:


version: '3.8'

services:
  mongodb:
    image: mongo
    container_name: mongodb
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=supersecret

Let’s start the container now:


$ docker-compose -f docker-compose-open.yml up -d
Creating mongodb ... done

Check the container status, docker ps:


$ dps
Container ID: e753a5985c96
Image: mongo
Command: "docker-entrypoint.s…"
Created: 2025-03-20 04:29:16 +0000 GMT
Status: Up 2 seconds
Ports: 0.0.0.0:27017->27017/tcp, [::]:27017->27017/tcp
Names: mongodb

The container is up and running, so far so good.

Let’s connect to the MongoDB using the same credentials as in the configuration file above:


$ docker exec -it mongodb mongosh --username admin --password supersecret
Current Mongosh Log ID: 67dbc40b54e05a0e5e6b140a
...
...
Using MongoDB:          8.0.5
Using Mongosh:          2.4.2

test>

We’ve passed the first hurdle, we’re inside the container and connected to MongoDB.

To exit, simply type exit at the prompt.

Let’s clean up by stopping and removing the container, so we can move to the next option.


$ docker stop mongodb
mongodb

$ docker rm mongodb
mongodb

Environment Variables


For this, we would create another configuration file, docker-compose-env.yml:


version: '3.8'
services:
  mongodb:
    image: mongo
    container_name: mongodb
    ports:
      - 27017:27017
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ADMIN_USER}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ADMIN_PASS}

You have two choices for creating environment variables: either use EXPORT key=value or define them when creating container:


$ export MONGO_ADMIN_USER=admin

$ export MONGO_ADMIN_PASS=supersecret

$ docker-compose -f docker-compose-env.yml up -d
Creating mongodb ... done

OR


$ MONGO_ADMIN_USER=admin MONGO_ADMIN_PASS=supersecret \
docker-compose -f docker-compose-env.yml up -d
Creating mongodb ... done

Check the container status, docker ps:


$ dps
Container ID: e753a5985c96
Image: mongo
Command: "docker-entrypoint.s…"
Created: 2025-03-20 04:32:10 +0000 GMT
Status: Up 33 seconds
Ports: 0.0.0.0:27017->27017/tcp, [::]:27017->27017/tcp
Names: mongodb

So all good, let’s connect to MongoDB:


$ docker exec -it mongodb mongosh --username admin --password supersecret
Current Mongosh Log ID: 67dbc7f7b8d8dedf8d6b140a
...
...
Using MongoDB:          8.0.5
Using Mongosh:          2.4.2

test>

Once that’s done, type exit at the prompt to exit.

We’ll clean up as before i.e. stop and remove the container.


$ docker stop mongodb
mongodb

$ docker rm mongodb
mongodb

Env File


Let’s create env file first, docker-compose.env as below:


$ echo "MONGO_ADMIN_USER=admin" > docker-compose.env

$ echo "MONGO_ADMIN_PASS=supersecret" >> docker-compose.env

Time to start the container with --env-file flag:


$ docker-compose --env-file docker-compose.env -f docker-compose-env.yml up -d
Creating mongodb ... done

Check the container status, docker ps:


$ dps
Container ID: d61324270839
Image: mongo
Command: "docker-entrypoint.s…"
Created: 2025-03-20 04:35:11 +0000 GMT
Status: Up 31 seconds
Ports: 0.0.0.0:27017->27017/tcp, [::]:27017->27017/tcp
Names: mongodb

Now it’s up and running. Good.

Let’s connect to MongoDB again.


$ docker exec -it mongodb mongosh --username admin --password supersecret
Current Mongosh Log ID: 67dbca84408a363eff6b140a
...
...
Using MongoDB:          8.0.5
Using Mongosh:          2.4.2

test>

Type exit at the prompt to exit so that we can proceed to the final option.

Finally, stop and remove the container:


$ docker stop mongodb
mongodb

$ docker rm mongodb
mongodb

Swarm Mode


This next part is a bit tricky as you’ll see.

First we need to enable Swarm mode.


$ docker swarm init

OR


$ docker swarm init --advertise-addr 172.19.28.199
Swarm initialized: current node (qz8w8ns05xvtmpsewhhsp9qiq) is now a manager.

Check if Swarm mode is active:

$ docker info | grep -i swarm
Swarm: active

Good, Swarm mode is now active.

Next, we’ll create two secrets one for the user and another for the password.

There are two ways to create secrets as shown below:


$ echo "admin" > mongo-user.txt

$ docker secret create mongo_user mongo-user.txt
x3lswvc8mkwh0x5opoyvkucca

and


$ echo "supersecret" | docker secret create mongo_pass -
5efjagekw2driudrs5z7j6ezc

We have created two secrets, let’s list them first:


$ docker secret ls
ID                          NAME         DRIVER    CREATED              UPDATED
5efjagekw2driudrs5z7j6ezc   mongo_pass             42 seconds ago       42 seconds ago
x3lswvc8mkwh0x5opoyvkucca   mongo_user             About a minute ago   About a minute ago

It’s time to create the configuration file, docker-compose-secret.yml as below:


version: '3.8'

services:
  mongo:
    image: mongo
    container_name: mongodb
    secrets:
      - mongo_user
      - mongo_pass
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME_FILE: /run/secrets/mongo_user
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_pass
    networks:
      - mongo_network

secrets:
  mongo_user:
    external: true
  mongo_pass:
    external: true

networks:
  mongo_network:
    driver: overlay
    attachable: true

To create a container in Swarm mode and use the secrets, we need to create the stack as follows:


$ docker stack deploy -c docker-compose-secret.yml mongo_stack
In a future release, --detach=false will become the default.
Creating network mongo_stack_mongo_network
Creating service mongo_stack_mongo

NOTE: The service name mongo_stack_mongo, it was auto-generated by Docker, which is the combination of stack name, mongo_stack and service name mongo.

Hang on, why isn’t the service name exactly as in the configuration file?

Well, if Docker used the service name exactly as defined in the configuration file, it would lead to naming conflicts in a multi-stack environment.

For example:


- Stack A has a service named db.
- Stack B also has a service named db.

If Docker didn’t prefix the service name with the stack name, both services would be named db, making it impossible to distinguish them in the Swarm cluster.

Can you change this behaviour?

No, Docker doesn’t provide a way to override this behaviour when using docker stack deploy.

The <stack>_<service> naming convention is enforced by design.

Check the container status, docker ps:


$ dps
Container ID: f85e4c9be83a
Image: mongo
Command: "docker-entrypoint.s…"
Created: 2025-03-20 04:37:31 +0000 GMT
Status: Up 19 seconds
Ports: 0.0.0.0:27017->27017/tcp, [::]:27017->27017/tcp
Names: mongodb

Let;s try to connect to MongoDB:


$ docker exec -it mongodb mongosh --username admin --password supersecret
Current Mongosh Log ID: 67dbcef14a1ae204cf6b140a
...
...
Using MongoDB:          8.0.5
Using Mongosh:          2.4.2

test>

Type exit at the prompt and to exit.

Finally, we’ll now remove the service.


$ docker service ls
ID             NAME                MODE         REPLICAS   IMAGE          PORTS
qg8b7aq1a3q3   mongo_stack_mongo   replicated   1/1        mongo:latest   *:27017->27017/tcp

$ docker service rm qg8b7aq1a3q3
qg8b7aq1a3q3

Last but not least, leave Swarm mode:


$ docker swarm leave


Keep Hacking !!

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me