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
.