Docker: keep your secrets secret
You’ve written a shiny app, plumber API, or an ETL process. Your orchestrating that work with Docker. In order for the application to work, you need to be able to use secret values.
How can you use secrets with a Docker image safely?
Example Dockerfile
Here is a very simple Dockerfile. Say the container is called
supersecret. When we run the Docker container we print a single
environment variable.
FROM rhub/r-minimal
CMD [ "R", "--slave", "-e", "cat(Sys.getenv('SECRET_USER'))"]
Run this with docker run --rm -t supersecret and you’ll see nothing
printed to the console. This is because the environment variable is not
actually available to the container.
How can you set the environment variables used by a container?
The ENV instruction
The ENV Docker instruction is used to specify environment variables
You can specify environment variables directly into the Dockerfile like
so:
FROM rhub/r-minimal
ENV SECRET_USER=josiah
CMD [ "R", "--slave", "-e", "cat(Sys.getenv('SECRET_USER'))"]
Running docker run --rm -t supersecret will print josiah to the
console! So that worked.
This is fine for things that dont need to be secret. For example maybe
you have something like ENV DEBUG=true to specify that this is a debug
build.
But if you have a secret, you shouldn’t place your secrets directly in the code of the Dockerfile.
Using --env
Another way to specify environment variables is to specify the
environment variables at run time using the --env flag. This accepts
key-value pairs for the environment variables.
For example
docker run --env SECRET_USER="ricky bobby" --rm -t supersecret
will print ricky bobby to the console.
This will work but it requires that you manually specify the environment
variables at run time when using docker run. And that can be
cumbersome and require some finagling.
And again, you dont want to write a bash script that hard codes those
values into a docker run call.
So what else can you do?
Using a separate file with --env-file
You shouldn’t store secrets in your R code. You should use a .Renviron
file. This looks like
KEY=value
SECRET_USER=josiah
SECRET_USER_PASSWORD=super-duper-very-secret
Tip
In many other languages and ecosystem, using a
.envfile with the same structure is used to set environment variables.
This would make the environment variables KEY, SECRET_USER and
SECRET_USER_PASSWORD available to your R session by running
Sys.getenv().
Now, you don’t want to actually copy this file into the docker container. What if you accidentally made the file available? Yikes!
Instead, you can pass the file directly using the --env-file flag.
This will capture the environment variables written in a file as a
KEY=value pair and make them available in your container.
docker run with file
Given the following files which define a Docker image called
supersecret
You will need to run docker run --env-file .env supersecret to set
your environment variables appropriately.