How build Node JS application using Docker for different staging environments - node.js

this should have been routine, but I haven't been able to find any way. I am using Node with Docker for packaging. I have three environments: dev, qa, and prod, as usual. I have three configuration files with numerous variables: dev-config.json, qa-config.json, prod-config.json. I need Docker to pick up files and package them as config.json inside the Docker image. How to go about pl.. Thx

For building an image with only the correct config file included, you can use --build-arg.
Add
ARG CONFIG_FILE
...
COPY $CONFIG_FILE config.json
in your docker file and then use
docker build --build-arg CONFIG_FILE=prod-config.json .
to build your image
EDIT
The other possibility is to put all your config files in your image and decide which one to use, when you startup the container. For instance, you could read the desired name of your config file from an environment variable (at runtime of the container, not to confuse with ARG and --build-arg at build-time of the image) which can be set when you start your container
Iw somewhere in your node app
// read the config file name from the environment variable
// and have a fallback if the environment variable is not defined
const configfilename = process.env.CONFIG_FILE || "config.json";
and when you start your container you can do
docker run --env CONFIG_FILE=prod-config.json YOURIMAGE
to set the environment variable. This way, you will have only one image.
A third possibility would be to not add your configs in the container at all, but load them from external volume that you mount when you run the container. If you have different volumes for diffent configs, you can again decide at startup, which volume to mount. As you can give your config file the same name on every volume, your app does not need to be aware of any environment variables, you just have to make sure, you use the correct path to your config file and all volumes have the same file structure.
Ie in your node app
const configfile = '/config/config.json';
and then you start your container mounting the correct config directory
docker run -v /host/path/to/prod-config:/config YOURIMAGE

Related

How to load external config file in Docker?

I am using Docker to build a Node app image. I am having my configurations in a YAML file which is located at source_folder/config.yaml.
When doing await readFile(new URL('../config.yaml', import.meta.url), 'utf8') in my index file it says file not found after running. However, doing - COPY config.yaml ./ in Dockerfile solves it but I don't want to copy my credentials in the image build.
Is there any solution I can load the config file after building the image?
Using ESM.
I use dotenv to load my env variables. I understand the need to not include it in builds. Docker provides a runtime solution of including these variables to your env by passing the file as an argument. So this is what I do to load my env while using docker run:
docker run -e VARIABLE_NAME=variable_value image_to_be_executed
# or
docker run --env-file path_to_env_file image_to_be_executed

pass filePath to dockerfile as variable _ nodeJS dockerode Docker

In my case, I am creating a config.json that I need to copy from the host to my container.
I figured out there is some option that I can pass args to my dockerfile.
so first step is :
1.create Dockerfile:
FROM golang
WORKDIR /go/src/app
COPY . . /* here we have /foo directory */
COPY $CONFIG_PATH ./foo/
EXPOSE $PORT
CMD ["./foo/run", "-config", "./foo/config.json"]
as you can see, I have 2 variable [ "$CONFIG_PATH", "$PORT"].
so these to variables are dynamic and comes from my command in docker run.
here I need to copy my config file from my host to my container, and I need to run my project with that config.json file.
after building image:
second step:
get my config file from user and run the docker image with these variables.
let configFilePath = '/home/baazz/baaaf/config.json'
let port = "8080"
docker.run('my_image', null, process.stdout, { Env: [`$CONFIG_PATH=${configFilePath}`, `$PORT=${port}`] }).then(data => {
}).catch(err => { console.log(err) })
I am getting this error message when I am trying to execute my code.
Error opening JSON configuration (./foo/config.json): open
./foo/config.json: no such file or directory . Terminating.
You generally don’t want to COPY configuration files like this in your Docker image. You should be able to docker run the same image in multiple environments without modification.
Instead, you can use the docker run -v option to inject the correct config file when you run the image:
docker run -v $PWD/config-dev.json:/go/src/app/foo/config.json my_image
(The Dockerode home page shows an equivalent Binds option. In Docker Compose, this goes into the per-container volumes:. There’s no requirement that the two paths or file names match.)
Since file paths like this become part of the external interface to how people run your container, you generally don’t want to make them configurable at build time. Pick a fixed path and document that that’s the place to mount your custom config file.

Setting environmental variables for node from host machine for build server

I'm using bitbucket pipelines as a build server.
I need to pass environmental variables from a host machine into a .env file which will then set the var values to be used in the build.
For example, lets say an environmental variable in a docker container running the build is AWS_ACCESS_KEY_ID.
In my .env file I'd like something like the following:
ACCESS_KEY=${AWS_ACCESS_KEY_ID}
I would then run the build and the ACCESS_KEY var would have a value equal to the env var in the docker container.
My current idea for a solution right now involves replacing values with sed, but that feels pretty hacky. Example:
.env file contains the following line:
ACCESS_KEY=<_access_key_replace_me_>
sed "s/<_access_key_replace_me_>/${AWS_ACCESS_KEY_ID}/g" .env
Any better solution than this?

Is posible do after build or have multiple build steps with webpack?

I have webpack frontend application that have config file (config/default.json). I read this with config-webpack. My config file should change between environments (staging/production/etc)
I have CI pipeline that build my js code, minimize and package in docker image of nginx to be published in docker registry (inmutable|agnostic of my config file).
My docker container must be initialize env key with execution value
ENVIRONMENT=staging|production|stress
In docker container i have connection to secrets store and retrieve config data for my execution ENVIRONMENT.
Doing all the build on container start is expensive.
I need post process my build to attach config/default.json to webpack bundle. No build all my project.

Application cannot access env variables while they are available on a container level

node.js application, built and deployed using docker-compose, doesn't see any custom set variables. console.log(process.env.VAR) logs undefined to console for any of those.
Variables are set using env_file property in yaml file. Only env_file property is used. There is an ENV value set in Dockerfile and it's accessible by the application.
docker exec -it <container-id> envdoes return all custom values. docker exec -it <container-id> sh returns only those set in base image - node-alpine (wiped out by exec?).
What can be wrong with the setup?
I've found that the issue is not with the compose file or wrong usage of env_file field.
The issue was with the env file itself. It used spaces when setting values. Like this: VAR = VAL instead of VAR=VAL.
While dotenv npm package allows this (I've used a sample that comes with a project as a base for deployment), docker and environment don't.

Resources