How to add Credentials to Docker ADD command?


Introduction

Security has always been a great threat to mankind. In IT the security of credentials is a tedious task. Here, we are going to discuss various methods to add the credentials to the docker container. Also, the most useful and secure methods are mentioned.

Methods

Adding credentials can be done in a lot of different ways. Some of the types are mentioned below. Each method has its place in the industry. Some are just rejected by the developers due to security issues and some works very well in the case of credential security.

  • Using the Build arguments in Dockerfile.

  • Using Environment variables in Dockerfile.

  • Using Docker Secrets.

Using build arguments

Passing credentials using build arguments is not preferred. This could be a security issue. One of the use cases of the build argument is mentioned below with an example.

Step 1 : Create a Dockerfile and a python program file.

This Dockerfile is going to create a python runtime on the ubuntu base image.

Example

#declare the build arguments that can be used before FROM in the # Dockerfile. ARG UBUNTU_VERSION=latest #use ubuntu as the base image. FROM ubuntu:$UBUNTU_VERSION #declare the build arguments that will be used after FROM command in #Dockerfile. ARG PYTHON_VERSION=2 #install the python on the ubuntu image RUN apt-get update -y && apt-get upgrade -y && apt-get install python$PYTHON_VERSION -y #set the working directory. WORKDIR /python/ #copy the python program to the Docker image. COPY program.py . #run this python program whenever this image is used to create a container. CMD python3 program.py

Now create a python file named “program.py”.

Output

print("********************Hello from TUTORIALSPOINT*********************")

Step 2 : Build the image

Example

$ docker build --build-arg PYTHON_VERSION=3 -t busy_python .

Output

Sending build context to Docker daemon 3.584kB
Step 1/7 : ARG UBUNTU_VERSION=latest
Step 2/7 : FROM ubuntu:${UBUNTU_VERSION}
---> 6b7dfa7e8fdb
Step 3/7 : ARG PYTHON_VERSION=2
---> Running in be6541523070
Removing intermediate container be6541523070
---> e3bef06439e8
Step 4/7 : RUN apt-get update -y && apt-get upgrade -y && apt-get install
python$PYTHON_VERSION -y
---> Running in e3ff50442993
Step 5/7 : WORKDIR /python/
---> Running in a147f39ec056
Removing intermediate container a147f39ec056
---> 166cfe1d9514
Step 6/7 : COPY program.py .
---> b09acbeb8f38
Step 7/7 : CMD python3 program.py
---> Running in eec7ec3982de
Removing intermediate container eec7ec3982de
---> 47dbde8eca00
Successfully built 47dbde8eca00
Successfully tagged busy_python:latest

Step 3 : Run the image

Now we will run this image and see if python says hello.

Example

$ docker run busy_python

Output

********************Hello from TUTORIALSPOINT*********************

Hence the build arguments worked.

The disadvantages of Build Arguments

This has security-related issues. The argument’s values can be seen by anyone who has access to the docker history.

$ docker history busy_python:latest IMAGE CREATED CREATED BY SIZE COMMENT 47dbde8eca00 12 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "pyth… 0B b09acbeb8f38 12 minutes ago /bin/sh -c #(nop) COPY file:a268373fa65eae71… 75B 166cfe1d9514 12 minutes ago /bin/sh -c #(nop) WORKDIR /python/0B 1bdd202b9d86 12 minutes ago |1 PYTHON_VERSION=3 /bin/sh -c apt-getupdat… 70.1MB e3bef06439e8 13 minutes ago /bin/sh -c #(nop) ARG PYTHON_VERSION=20B 6b7dfa7e8fdb 11 days ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 11 days ago /bin/sh -c #(nop) ADD file:481dd2da6de715252… 77.8MB

Hence this is not a secure method for credentials.

Using Environment Variables

The build arguments are only available till the build of the image. The environment variables are also available to the image and the container after the build. That is the main difference between build arguments and environment variables.

Here we will use environment variables to pass the credentials to the MySQL database.

Step 1 : Create a Dockerfile

#use the mysql as the base image FROM mysql #set the required root password ENV MYSQL_ROOT_PASSWORD mypassword@root

Step 2 : Build the image

Example

$docker build -t mysql_test .

Output

Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM mysql
---> 7484689f290f
Step 2/2 : ENV MYSQL_ROOT_PASSWORD mypassword
---> Running in 80d7ad7561d4
Removing intermediate container 80d7ad7561d4
---> a5168465919b
Successfully built a5168465919b
Successfully tagged mysql_test:latest

Step 3 : Run the image without passing the credentials as that has been already set in the Dockerfile.

$docker run -d --name cont mysql_test 943d02de21c555618ae9eb4b416faccf00d989020c565a1336afb4743cb6b7b1

Step 4 : Get inside the MySQL container and use the credentials to start the database.

Example

$ docker exec -it cont /bin/bash

Now start accessing the database.

# mysql -h 172.17.0.2 -P 3306 -u root –pmypassword

Output

mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.31 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>

Disadvantages

Here MYSQL also gave us a warning about using the password on the command line. This is unsafe to use the password directly on the command line. Also, we should not use the password in the Dockerfile which could be seen using the inspect command in the docker.

Example

$ docker inspect -f "{{ .Config.Env }}" cont

Output

[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin GOSU_VERSION=1.14 MYSQL_MAJOR=8.0 MYSQL_VERSION=8.0.31-1.el8 MYSQL_SHELL_VERSION=8.0.31-1.el8 MYSQL_ROOT_PASSWORD=mypassword]

Hence the password is visible.

Using Docker Secrets

If an image is created on your local system and shared with someone else or even published on the Docker Hub. The main aim of Docker Secrets is that the credentials used while creating the image should not be accessible to the user of the image.

In this example, we will create a service container and provide a secret file. Then, commit the container to form an image for later use. Now, run a container using this image and check if the secret message is present or not.

Step 1 : Create a Docker Secret

First, we need to initialize the Docker Swarm manager.

$docker swarm init

If your Docker Swarm does not start due to IP resolution use --advertiseaddr=ip_of_the_machine and --listen-addr=0.0.0.0

$ docker swarm init --advertise-addr <ip_of_machine> --listen-addr 0.0.0.0

Output

Swarm initialized: current node (eksm5jqv8sn8jlr8fwq31n6ht) is now a manager.
To add a worker to this swarm, run the following command:
   docker swarm join --token SWMTKN-1- 1okpgh4spk3nab0mjjzk3c2nx3a68p3l1ww06bx8fu20nvpr0j90vxfk3dsyqvw3s1edzr5k4ou 192.168.43.97:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Now, create Docker Secret using the below command.

Example

$echo 'secret credentials for TUTORIALSPOINT database' | docker secret create ttrlpnt_secret_file -

Output

qmry8v6wsihjuizgtg292ozau

To get complete details about the Docker secret file, use the below command.

Example

$ docker secret ls

Output

ID NAME DRIVER CREATED UPDATED qmry8v6wsihjuizgtg292ozau ttrlpnt_secret_file 2 hours ago 2 hours ago

This means our Docker Secret is ready to be used.

Step 2 : Create a service

We will create a mysql service that will take the above-created Docker Secret as the root password.

Example

$ docker service create --name=ttrlpnt_mysql --secret source=ttrlpnt_secret_file,target=ttrlpnt_secret_file -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/ttrlpnt_secret_file" mysql:latest

Output

image mysql:latest could not be accessed on a registry to record its digest. Each node will access mysql:latest independently, possibly leading to different nodes running different versions of the image.
n7651xa5porbsf4l948vwa33c
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged

Check if the service is running.

Example

$ docker ps

Output

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
27fcefc610c8 mysql:latest "docker-entrypoint.s…" 35 seconds ago Up 31 seconds 3306/tcp, 33060/tcp ttrlpnt_mysql.1.bzkxffaovta8mj5q33ap7z1tl

Step 3: Exec inside the container

Now, we will get inside the container and get the content of the secret file stored in it i.e. the root password.

Example

$ docker exec ttrlpnt_mysql.1.bzkxffaovta8mj5q33ap7z1tl bash -c 'cat /run/secrets/ttrlpnt_secret_file'

Output

secret credentials for TUTORIALSPOINT database

Hence the secret file is present.

Step 4 : Check if the committed image file has the secret data

Create an image from this container.

Example

$ docker commit ttrlpnt_mysql.1.bzkxffaovta8mj5q33ap7z1tl secret_mysql:v1

Output

sha256:d5fcdc6c3b093485146dfd8e89b2f8be133090bc4ecf3995f4ce409dec30c523

Now inspect the image and check if we get the password for the root.

Example

$ docker inspect -f "{{ .Config.Env }}" secret_mysql:v1

Output

[MYSQL_ROOT_PASSWORD_FILE=/run/secrets/ttrlpnt_secret_file
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
GOSU_VERSION=1.14 MYSQL_MAJOR=8.0 MYSQL_VERSION=8.0.31-1.el8
MYSQL_SHELL_VERSION=8.0.31-1.el8]

Hence only the path is mentioned and the credentials are secure.

Conclusion

In this article. We learned various ways to pass the credentials to the Docker containers. The security issues related to them are also discussed and solutions are also provided. Using Docker Secrets is one of the most useful and secure ways to give your logins.

Updated on: 05-Jan-2023

4K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements