Hi, I'm setting up a Node.js app to run in a Docker container, and I want it to be able to get its environmental configuration at run time. It seems like the safest way is to let the container mount a host file system that contains the .env file, and then tell dotenv where to find it. This is because I don't want to build the .env file into the Docker container, since the contents will change from run to run.
So, I tried what seems to be the right way to do this, and that's to pass in an environment variable DOTENV_CONFIG_PATH that has a value of the full path to the .env file as seen from inside the container. But dotenv isn't seeing it. I know the environment variable is getting set, and I know that the file is visible in the container. So I don't know what's going wrong.
I'm using dotenv 6.2.0. And my the environment variable is set like this:
DOTENV_CONFIG_PATH=/app/.env
I tried all lowercase, too, but it still didn't work. What could I be doing wrong?
Can you reproduce this without Docker? A broken test case would be best. Just trying to eliminate as many variables as possible.
If you're just trying to get something to work, you might try ripping out dotenv and trying their --env-file arg which follows our basic rules.
If Node.js is more your thing, I saw https://github.com/zeit/next.js/pull/5910 the other day which has me wondering if we could remove this env var config and use that instead...
OK, I wrote the simplest test case I could think of, and get the same behavior without Docker in the mix. It appears that dotenv is always ignoring the value of the environment variable DOTENV_CONFIG_PATH and looking only in the project's working directory for the .env file.
require('dotenv').config();
var assert = require('assert');
console.log("process.env.DOTENV_CONFIG_PATH is set to: " + process.env.DOTENV_CONFIG_PATH)
console.log("process.env.TEST_VALUE is set to: " + process.env.TEST_VALUE)
var fs = require('fs');
if (fs.existsSync(process.env.DOTENV_CONFIG_PATH)) {
console.log('The .env file exists')
}
assert(process.env.TEST_VALUE, "foo");
Using that code in a file called dotenvtest.js, I created a file ./env/.env and ran the code like this:
DOTENV_CONFIG_PATH=`pwd`/env/.env node dotenvtest.js
The assert fails (AssertionError [ERR_ASSERTION]: foo). But if I create a file ./.env with contents TEST_VALUE=bar, then the app prints that process.env.TEST_VALUE is set to: bar.
Oh, and yes I'm using Node.js, so I could go use the other approach you recommended. I just liked and have been using dotenv-safe, which is based on dotenv. It suffers from this same bug, of course.
Aha, I found that if I replace this...
require('dotenv').config();
...with this...
require('dotenv').config({path: process.env.DOTENV_CONFIG_PATH});
...then I get the expected behavior. Maybe I was using the library wrong? Or maybe this is a workaround? I don't know, but from reading the docs, I thought that the library would automatically look at DOTENV_CONFIG_PATH and use it, without me telling the library to do that by passing in the value to the config function.
Thanks for the test case. It really helps demonstrate what is going on. As you've figured out by now, configuration via environment variables is only supported when preloading the module. Since you are including dotenv in your source, you need to specify configuration there and can use any environment variables you wish (no magic from dotenv).
You can use import 'dotenv/config'; or require('dotenv/config'); to release this magic.
Most helpful comment
You can use
import 'dotenv/config';orrequire('dotenv/config');to release this magic.