2

So I'm very new to Docker and I'm just confused in regards to how it handles environment variables.

I know that if you use environment variables in your app you can define them in the Dockerfile using ENV key=value however doesn't this entirely defeat the purpose of env vars?

Reasoning: When we push the source code to github, the Dockerfile and all its contents are in plain text and so are our env vars are just exposed. Also say that you don't push the Dockerfile to github but it is still used to make the image which can be inspected in Docker Desktop which again reveals the env vars in plain text.

So how do we properly deal with environment variables in Docker?

I use a .env file in my project structure. Is there anyway we could configure Docker to just use the .env file rather than having to explicitly type ENV key=value for every variable we have?

Thank You!

darkstar
  • 829
  • 11
  • 23
  • yes, you can copy files into your container and run a ~/.bashrc script for new shells within the container, but also, not all env vars are intended to be secrets. For example, you can set `ENV user=newusername` and this may be a useful thing to set up in your container. There is extensive documentation on [docker secrets](https://docs.docker.com/engine/swarm/secrets/) as well as other ways of managing secrets when deploying, so your last question is application specific and way too broad to answer. – Michael Delgado Sep 01 '21 at 06:14
  • You only implicitly indicate what you think "the whole purpose of environment variables" is. But you seem to have an incorrectly narrow opinion about their purpose. This comes across more like a rant than a question. – Raedwald Sep 01 '21 at 06:39
  • As to my understanding, env vars are meant to hold sensitive data. Of course they can hold non sensitive data but the use case 99% of the time is sensitive data. And yeah Docker has been annoying me cause I can’t figure out exactly why or how to use it. – darkstar Sep 01 '21 at 07:18

3 Answers3

2

You can pass environment variables when running the container either by defining them then and there or by loading them from a file.

For example, if you are planning to use a file,

docker run --env-file ./env.list ubuntu bash

This file should use the syntax <variable>=value (which sets the variable to the given value) or (which takes the value from the local environment), and # for comments.

For more information about different practices of using environment variables, please refer Set environment variables (-e, --env, --env-file).

RrR-
  • 1,251
  • 3
  • 15
  • 32
  • Is ``./env.list`` point to a file in the current directory that holds the env vars? – darkstar Sep 01 '21 at 06:28
  • 1
    Yes. Also, you should be able to define this in a different location and provide the correct path. – RrR- Sep 01 '21 at 06:31
1

You can use --env-file option to pass a file in the docker run command. That file is different from the Dockerfile.

--env-file documentation

usuario
  • 2,132
  • 1
  • 10
  • 26
1

Setting an ENV in a Dockerfile is fine; it no more "defeats the purpose of environment variables" than setting PS1 to a fixed value in your .profile file.

Sometimes environment variables are used to control features of a language runtime. A good example of this is the PYTHONUNBUFFERED variable, which causes the Python runtime to write print() calls to stdout immediately. In Docker you usually want to set this to avoid problems with Python container output just not appearing. An end user wouldn't want to override this typically.

FROM python:3.9
# We will _always_ want unbuffered mode when running in Docker
ENV PYTHONUNBUFFERED=1

Another path that's useful is to use environment variables to provide command-line options. Using the Node yargs, command-line parsing library, for example, we can set it up to recognize both --arguments and $ARGUMENTS:

const argv = require('yargs/yargs')(process.argv.slice(2))
  .env('GREETER')
  .option('greeting', { default: 'Hello' })
  .option('place', { default: 'world' })
  .argv;
console.log('%s, %s', argv.greeting, argv.place);

When you run this, you could try to override the command part

docker run --rm my/greeter node greeter.js --place 'Stack Overflow'

but if you have many options that come from various sources it can be more convenient to specify the options via environment variables. (This is doubly true, even without Docker, if some of the options might only be present sometimes; it's easier, safer, and more portable to maybe set an environment variable than to maybe include an option in a shell command.)

docker run --rm -e GREETER_PLACE='Stack Overflow' my/greeter

This approach would also let you provide a default value for a single option in a Dockerfile, if simply the fact of running in a container is different enough to merit a different default from the code.

FROM node:14
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY greeter.js .
ENV GREETER_PLACE=Docker
CMD ["node", "greeter.js"]

You're right that ENV settings in an image are not secret; they can be retrieved by running docker inspect on the image, or (usually) by docker run --rm the-image env.

David Maze
  • 130,717
  • 29
  • 175
  • 215