How to get access to docker ENV variables in nodeJS application - javascript

I'm using this Dockerfile:
FROM node:8.4.0
COPY . /
ENV MONGO_URL=mongodb://mongo-container/data
ENV PORT=80
EXPOSE 80
CMD node /index.js
In the index.js file I want to check for the ENV variables. As the docker image is used in productive, I would run the app with development environment if the ENV variable is not set.
Something similar to this:
index.js
const mongoUrl = ENV.MONGO_URL || 'mongodb://localhost:3001'
Running the Docker image should use the productive mongoDB, running locally should use localhost DB

process.env object contains all the user environment variables. Check link for more info https://nodejs.org/api/process.html#process_process_env

Related

.env file not updating in local environment in react js

I do have a .env file in my react project and using dotenv package to read the environment variables. I did a console log of the environment variables. I had initialized few variables in the beginning in .env file and was being read perfectly.
Later I changed some data in the .env file and restarted the local server, but new changes were not being reflected. EVEN after deleting the .env file and starting the server, the same old variables are loaded.
I know it's a cache issue but could not figure out a way to reset it.
I am using npm start command to start the server.
Use REACT_APP prefix
You need to declare variables with REACT_APP prefix as per the documentation.
REACT_APP_API_KEY = 'XXXXXXXX'
REACT_APP_AUTH_DOMAIN = 'XXXXXXXX'
REACT_APP_DATABASE_URL = 'XXXXXXXX'
REACT_APP_PROJECT_ID = 'XXXXXXXX'
REACT_APP_STORAGE_BUCKET = 'XXXXXXXX'
REACT_APP_MESSAGING_SENDER_ID = 'XXXXXXXX'
REACT_APP_API_ID = 'XXXXXXXX'
REACT_APP_MEASUREMENT_ID = 'XXXXXXXX'
And similarly, access them with the prefix in your code
console.log(process.env.REACT_APP_PROJECT_ID);
Note: You need to restart the dev server every time you update the env file to consume the changes.
Changing env variables requires to restart node server to take the new values.
But sometimes , it doesn't work , so you mush apply a cache reset.
npm start --reset-cache

REACT APP not access the google cloud run environment variables

I am using GitLab ci as my CI/CD tool. I am deploying the dockerized react app to cloud run but I am not able to access the environment variables declared on cloud run. Thank you!
Dockerfile
# build environment
FROM node:8-alpine as react-build
WORKDIR /app
COPY . ./
RUN npm install
RUN npm run build
# server environment
FROM nginx: alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
COPY --from=react-build /app/build /usr/share/nginx/html
ENV PORT 8080
ENV HOST 0.0.0.0
EXPOSE 8080
CMD sh -c "envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
gitlab-ci.yml
default:
image: google/cloud-sdk:alpine
before_script:
- gcloud config set project PROJECTID
- gcloud auth activate-service-account --key-file $GCP_SERVICE_CREDS
stages:
- staging
- production
staging:
stage: staging
environment:
name: staging
only:
variables:
- $DEPLOY_ENV == "staging"
script:
- gcloud builds submit --tag gcr.io/PROJECTID/REPOSITORY
- gcloud run deploy REPOSITORY --image gcr.io/PROJECTID/REPOSITORY --platform managed --region us-central1 --allow-unauthenticated
production:
stage: production
environment:
name: production
only:
variables:
- $DEPLOY_ENV == "production"
script:
- gcloud builds submit --tag gcr.io/PROJECTID/REPOSITORY
- gcloud run deploy REPOSITORY --image gcr.io/PROJECTID/REPOSITORY --platform managed --region us-central1 --allow-unauthenticated --set-env-vars NODE_ENV=production
Credits to Guillaume Blaquiere because this answer is based on his post from this thread.
According to React documentation:
The environment variables are embedded during the build time. Since Create React App produces a static HTML/CSS/JS bundle, it can’t possibly read them at runtime. To read them at runtime, you would need to load HTML into memory on the server and replace placeholders in runtime.
Most likely what happens is that you expose static files to your users and the users get the files and load them in their browser like this:
console.log("REDIRECT", process.env.REACT_APP_API_END_POINT)
This returns null because the users' browser execute the Javascript and read the env variable on the current environment: the users' browser. You should have an execution that run on Cloud Run to use the env vars. If the code is ran on user side (in their browser), the env vars will not appear.
As I understand it, you want to access environment variables declared on GCP such as $GCP_SERVICE_CREDS, $PROJECTID, $REPOSITORY and others on your Gitlab pipeline.
To do this, go to Gitlab settings then click on CI/CD. Once there, click on the Expand button in front of Variables and you add your various GCP variables with their Values.

Login credentials for puppeteer running on a rocker container

I am running puppeteer on a docker container in headless mode to test our website. The first page is the login page. The puppeteer script and docker files are stored in an internal git repo. What is a good way of securely storing the login credentials?
Obviously not as a file in the fit repo. Docker secrets is an option, what are some other options? I need puppeteer to read them without any user intervention.
You can pass the credentials as environment variables to your docker container. The following line starts the docker container and passes the variables LOGIN_USER and LOGIN_PASSWORD from your host to your docker environment. That way, you specify them as environment variables inside your host system, but you do specify them inside your code or repository.
Starting Docker
docker run -e LOGIN_USER LOGIN_PASSWORD [...]
Inside the container
Inside your container, you then use the variable by accessing process.env.LOGIN_USER and process.env.LOGIN_PASSWORD like this (example using page.type):
page.type('#input-field', process.env.LOGIN_USER);
Setting the environment variables
There are multiple options to set the environment variables. You can either set the permanently (in case you want to run multiple docker containers) or only for a single command. Check out this answer on askubuntu for more information.

How to set port for express server dynamically?

This is the question mostly asked by the beginners, as I had this question when I was starting out
How to set port for express without needing to hardcode or even choose port yourself? This is the question I had when I was starting out in node and express (I am still a beginner, have lots of things to learn). Things I wanted know other than that included,
What is difference between using app.set('port', portNum) and directly using port number in app.listen(portNum)?
How to set port for express without needing to hardcode or even choose port yourself?
###Option 1: Environment variable (recommended)
Often times you will deploy your app to a hosting provider like Heroku. Depending on how the host is configured, the system will dynamically set an environment variable and your app will need to get the port from this variable. For example, the hosting provider might run a command like this when it runs your app:
$ PORT=1234 npm start
... and within your code, you can access this variable like this:
const port = process.env.PORT;
app.listen(port);
Pro tip: Most hosting providers let you define custom environment variables too. You can test this locally by creating arbitrary variables like this:
$ FOO=bar ADMIN_EMAIL=joe#example.com npm start
...and access those variables from code like this:
const foo = process.env.FOO; //-> "bar"
const adminEmail = process.env.ADMIN_EMAIL; //-> "joe#example.com"
Option 2 - environment-specific config files (also highly recommended)
Using a config library like config and/or dotenv allows you to easily manage environment-specific config options. Your folder structure would look like this (note the names of the files):
|- config
|- default.json
|- testing.json
|- production.json
|- src
|- app.js
You then define your "default" variables and environment-specific variables:
default.json
{
"port": "3030",
"adminEmail": "dev#example.com"
}
testing.json
{
"port": "5555"
}
production.json
{
"adminEmail": "admin#example.com"
}
The config library will always use the default variables. When you are on testing it will use the default admin email and a different port. When you are on production it will use the default port but a different admin email. The way you define your "node environment" is like this (notice we use the same name as the JSON config files):
$ NODE_ENV=testing npm start
$ NODE_ENV=production npm start
Pro tip: Your configuration files can reference environment variables too! Continuing with our example from Option 1 above, you can define your production config like this:
production.json
{
"port": "PORT"
}
The config library will look for any environment variables named "PORT" and will use that value. Putting it all together, your final command to run your app might look like this:
$ NODE_ENV=production PORT=47861 npm start
Pro tip: - dotenv can be used alongside the config library for ultimate environment variable management!!
2. What is the difference between using app.set('port', portNum) and directly using port number in app.listen(portNum)?
Express allows you to set application variables using app.set - but this is just a fancy way for defining variables. You can later get the values for these variables using app.get.
Sooner or later, you are going to need to tell your app to listen for traffic on a specific port. You could do something like this:
const app = express();
app.set('port', process.env.PORT);
app.use((req, res) => { ... });
app.listen(app.get('port'));
Answers that I found to my questions
1. How to set port dynamically?
I found out that you can use number 0 in app.listen() to let express select the port randomly, then I soon found out that I now had a problem I didn't know which port to access to know if my server was running or not. So simple answer to that was to output the app.address().port in console
so a Simple express server will look like this
let http = require('http');
let express = require('express');
let app = express();
app.use('/', serveStatic('./public'));
app.get('/', (req, res) => {res.render('index')});
let server = http.createServer(app);
server.listen(0, () => {
console.log(server.address().port)
})
2. What is difference between using app.set('port', 1234) and directly using port number in app.listen(1234)?
In my experience/knowledge (honestly speaking its almost equivalent to zero) I came to believe that, app.set() sets the property in app.locals and allows retrieving of that information later (which is somewhat similar to creating a variable), but I recently read that app.set() allows the value stored to be used in you template engine and other places, which makes it quite different.
What is the difference between setting a property on app.locals and calling app.set()?
Unix [1]:
$ PORT=1234 node app.js
More permanently (for a login session) [2]:
$ export PORT=1234
$ node app.js
In Windows:
set PORT=1234
In Windows PowerShell:
$env:PORT = 1234
[1] Process-lived, while the parent process that initiates is still running. If you close terminal, variable dies.
[2] Close terminal, open a new one, variable still alive.
config.js
let config = {};
// PORTS
config.port = {};
config.port.alpha = 4050; // Server 1
config.port.beta = 4051; // Server 2
.....
module.exports = config;
app.js
const express = require("express"),
config = require("./config");
....
app.set('port',config.port[process.env.SERVER_NAME]);
app.listen(app.get('port'),function(){
console.log("Server running at "+app.get('port'));
});
Starting server
SERVER_NAME=alpha node app.js
SERVER_NAME=beta node app.js

MongoDB disabled by default [duplicate]

I have to meteor application in local (admin and client). Applications run on different port 3000 and 3003. I want to use both app should use the same DB. export MONGO_URL=mobgodb://127.0.0.1:3001/meteor will be okay. But I would like to know any argument to pass with meteor command to setup environment variable to use the same DB.
If you are looking for a start script you could do the following:
In the root of your app, create a file called start.sh:
#!/usr/bin/env bash
MONGO_URL=mobgodb://127.0.0.1:3001/meteor meteor --port 3000
Then run chmod +x start.sh
You can then start your app just by typing ./start.sh

Categories