Kubernetes: volumeMount, emptyDir, and env equivalents during local Docker development

Kubernetes has a rich way of expressing volumes/ volumeMounts for mounting files, emptyDir for ephemeral directories, and env/envFrom for adding environment variables to your container definition running on a Kubernetes cluster.

However, if you are actively iterating on the development of an image, it may slow you down to require a deployment to a remote Kubernetes cluster or even a small local Kubernetes implementation.

In this article, I will show you how to use the Docker equivalent of volumes/volumeMounts, emptyDir, and env/envFrom so that you can develop and test on your local Docker service without needing Kubernetes.

Equivalent of volumes/volumeMounts

You can mount local files to a specific location using the ‘-v’ volume flag.

Here is an example of mounting a local file at ‘/etc/nginx/nginx.conf’ which would control the main configuration of an NGINX based container.

docker ... -v /my/local/path/nginx.conf:/etc/nginx/nginx.conf:ro

Equivalent of emptyDir

You can create ephemeral directories using a tmpfs mount.

The example below creates a local directory only available inside the container at ‘/var/log/nginx’ that could be used to write logs.

docker ... --mount type=tmpfs,destination=/var/log/nginx

Equivalent of env/envFrom

Set a single environment variable using the ‘env’ flag.

docker ... --env key=value

Set a group of key/value pairs from a file using the ‘env-file’ flag.

docker ... --env-file env.properties

Example Project

I’ve uploaded a project to github to test the above scenarios.

sudo apt install git curl make -y

git clone https://github.com/fabianlee/k8s-vol-and-vars-for-docker.git
cd k8s-vol-and-vars-for-docker

root_dir=$(realpath .)

Deployment to Kubernetes

First, let’s get a baseline of functionality used in our Kubernetes deployment.

  • volumeMounts for /usr/share/nginx/html/index.html (main content for HTTP)
  • volumeMounts for secret at /usr/share/nginx/html/.htpasswd (BASIC auth)
  • volumeMounts for /etc/nginx/nginx.conf (config and BASIC auth)
  • emptyDir for /var/log/nginx (access and error logs)
  • inline static env var “my_key”
  • envFrom for all keys in file “env.properties”
cd $root_dir

# view, then apply manifests
make k8s-apply

# run tests against kubernetes deployment
make k8s-test

The output of the tests will show delivery of the custom index.html, BASIC auth for restricted content (which shows that nginx.conf and .htpasswd are in place), and the environment variables that are both static as well as from the env.properties file.

Test equivalents in Docker

If you do not already have Docker installed, you can refer back to my previous article for installation steps.  Then deploy the same Docker image with mounts and environment variables matching the Kubernetes deployment.

sudo apt install git curl make -y
cd $root_dir

# build image
make

# run docker container in background
make docker-run-bg

# run tests against docker container running locally
make test

The output of the tests will show delivery of the custom index.html, BASIC auth for restricted content (which shows that nginx.conf and .htpasswd are in place), and the environment variables that are both static as well as from the env.properties file.

Test of public content
curl http://localhost:8080

Hello, World! k8s deployment with configmap, secret, and log emptyDir


Test of restricted content
curl -u "myuser:MyF4kePassw@rd" http://localhost:8080/restricted/

Hello, World! k8s deployment with configmap, secret, and log emptyDir


Check environmental variables
"docker" exec -it k8s-vol-and-vars-for-docker /bin/sh -c "env | sort | grep ^[a-z]"
foo=bar
fruit=apple
my_key=My value
vegetable=spinach

With these equivalent file mounts and environment definitions, you can get a tight write-deploy-test lifecycle that can be used to validate correctness of your image.  And only then push the image to a registry accessible by your Kubernetes cluster.

Other image dependencies

If your image has other dependencies that cannot be substituted (e.g. service dependencies), and you must develop/test within Kubernetes, you should consider a small local Kubernetes implementation like microk8s or k3s.

 

REFERENCE

docker, declare environment files

docker, tmpfs

docker, volumes

jeffgeerling.com, mounting k8s secret single file inside pod

yogihosting, mounting configmap as file