So,
I am using NUXT
I am deploying to google cloud run
I am using dotenv package with a .env file on development and it works fine.
I use the command process.env.VARIABLE_NAME within my dev server on Nuxt and it works great, I make sure that the .env is in git ignore so that it doesnt get uploaded.
However, I then deploy my application using the google cloud run... I make sure I go to the Enviroments tab and add in exactly the same variables that are within the .env file.
However, the variables are coming back as "UNDEFINED".
I have tried all sorts of ways of fixing this, but the only way I can is to upload my .env with the project - which I do not wish to do as NUXT exposes this file in the client side js.
Anyone come across this issue and know how to sort it out?
DOCKERFILE:
# base node image
FROM node:10
WORKDIR /user/src/app
ENV PORT 8080
ENV HOST 0.0.0.0
COPY package*.json ./
RUN npm install
# Copy local nuxt code to the container
COPY . .
# Build production app
RUN npm run build
# Start the service
CMD npm start
Kind Regards,
Josh
Finally I found a solution.
I was using Nuxt v1.11.x
From version equal to or greater than 1.13, Nuxt comes with Runtime Configurations, and this is what you need.
in your nuxt.config.js:
export default {
publicRuntimeConfig: {
BASE_URL: 'some'
},
privateRuntimeConfig: {
TOKEN: 'some'
}
}
then, you can access like:
this.$config.BASE_URL || context.$config.TOKEN
More details here
To insert value to the environment variables is not required to do it in the Dockerfile. You can do it through the command line at the deployment time.
For example here is the Dockerfile that I used.
FROM node:10
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm","start"]
this is the app.js file
const express = require('express')
const app = express()
const port = 8080
app.get('/',(req,res) => {
const envtest = process.env.ENV_TEST;
res.json({message: 'Hello world',
envtest});
});
app.listen(port, () => console.log(`Example app listening on port ${port}`))
To deploy use a script like this:
gcloud run deploy [SERVICE] --image gcr.io/[PROJECT-ID]/[IMAGE] --update-env-vars ENV_TEST=TESTVARIABLE
And the output will be like the following:
{"message":"Hello world","envtest":"TESTVARIABLE"}
You can check more detail on the official documentation:
https://cloud.google.com/run/docs/configuring/environment-variables#command-line
Related
So I write a Twitch Chat Bot. Dockerized (docker compose), Node.js v16 with express.
For my authorize-page someone can use to authorize my bot on Twitch API I used the route /auth/request like
this.serverUrl = serverUrl;
this.port = port;
this.app = express();
this.app.use(express.static(__dirname + '/frontend/'));
//Landingpage to authorize App for channel
this.app.get('/auth/request/', (req:any, res:any) => {
console.log('/');
var indexhtml = new Replacer().replace(__dirname + '/frontend/auth/request/index.html', '%SERVER_URL%', this.serverUrl);
res.send(indexhtml);
});
(I am using '%SERVER_URL%' as a placeholer that gets replaced by my localhost or domain-adress.)
First time, there was error, replacing the string and twitch API respondet an error, of course.
But after this, I was not able to change the behavior of the route anymore. Further more, It was still available aber commenting it completely out.
Serveral restarts did not help. Even with
docker-compose up --build --force-recreate
I put the route back in, fixed the error an changed the route to "/". I wanted to do that anyway. Here it works fine but at the old route, it is still available with the replace error.
I thougt of some kind of weird deamon services, that are still running, but thats not a thing since it is not available when the container is not running.
I have no further ideas...
How can I get rid of this annoying route? It should not exist anymore.
docker-compose.yml
version: '0.1'
services:
node:
container_name: sacrificulus
build: ./app
ports:
- "3000:3000"
volumes:
- D:\Projects\WebProjects\AlfredServes\app:/app/token_store
command: ["./node_modules/.bin/ts-node", "./src/bot.ts"]
Dockerfile
FROM node:16
WORKDIR /app
COPY . /app
ENV TWITCH_CLIENT_ID=12345mytwitchclientid54321
ENV URL_LIVE=https://bot.example.com
ENV PORT_LIVE=80
ENV URL_LOCAL=http://localhost:
ENV PORT_LOCAL=3000
ENV LIVE_OR_LOCAL=local
#ENV LIVE_OR_LOCAL=live
RUN npm install
Did anyone had a similar bahavior?
( Sorry for my code quality :D )
sorry from below's answer. but if you think the code is not changed, try to turn down the container, delete and rebuild. using relative path instead of absolute path for volumes might help.
in express code, why dont you use res.redirect(`process.env.URL_REDIRECT`) ?
with URL_REDIRECT pointing either your URL_LIVE or URL_LOCAL.
or even better, make the logic inside your express code,
const URL_REDIRECT = (LIVE_OR_LOCAL === 'live')? process.env.URL_LIVE : process.env.URL_LOCAL
also, why you set env in dockerfile? not in docker-compose? its available (read: https://nodejs.dev/en/learn/how-to-read-environment-variables-from-nodejs/ )
also, just noticed, you are using docker-compose version 0.1 instead of recommended of version 3
at work I need to make it possible to change the environmet variables at runtime, from an Azure web service, through docker and nginx.
I tried this, this and some similar solutions, but I couln't get any of them to work.
I also couldn't find any solution online or any article/thread/post that explained if this is even possible, I only always find the text that vite statically replaces the env variables at build time.
During our CI/CD pipeline vite gets the env variables but our Azure admins want to be able to configure them from Azure, just for the case of it.
Does anyone know if this is possible and or maybe has a solution or some help, please ? :)
It is not possible to dynamically inject Vite env variables. But what is possible, is to change the window object variables (assign them on runtime).
WARNING!!! DO NOT EXPOSE ANY SENSITIVE VARIABLES THROUGH THE WINDOW OBJECT. YOUR FRONT-END APPLICATION SOURCE IS VISIBLE TO ANYONE USING IT
Steps:
Create your desired env files and place them in <rootDir>/public. Let's call them env.js and env-prod.js.
Inside your env.js and env-prod.js You want to assign your desired variables using var keyword. Also, you will have to reference these values in your source like window.MY_VAR to be able to use them.
Create a script tag inside your <rootDir>/index.html like this:
<script type="text/javascript" src="./env.js"></script>.
IMPORTANT!!! type="text/javascript" is important, because if You specify module, Vite will include your env.js source inside your minified index.js file.
Vite config (optional):
plugins: [react(), tsConfigPath()],
build: {
emptyOutDir: true, // deletes the dist folder before building
},
});
How to serve the env files on runtime. Create a node server which will serve your frontend application. But before serving the env.js file, depending on our process.env.ENVIRONMENT you can now choose which env.js to serve. Let's say my node server file is stored at <rootDir>/server/server.js:
const express = require("express");
const path = require("path");
const app = express();
const env = process.env.ENVIRONMENT || "";
console.log("ENVIRONMENT:", env);
const envFile = path.resolve("public", env ? `env-${env}.js` : "env.js");
const indexFile = path.resolve("dist", "index.html");
app.use((req, res, next) => {
const url = req.originalUrl;
if (url.includes("env.js")) {
console.log("sending", envFile);
// instead of env.js we send our desired env file
res.sendFile(envFile);
return;
}
next();
});
app.use(express.static(path.resolve("dist")));
app.get("*", (req, res) => {
res.sendFile(indexFile);
});
app.listen(8000);
Serve your application build while running node ./server/sever.js command in your terminal.
Finally:
my env.js contains var RUNTIME_VAR = 'test'
my env-prod.js contains var RUNTIME_VAR = 'prod'
After I set my process.env.ENVIRONMENT to prod. I get this file served:
My Solution is that it schould work with the links from my question.
I use this approach and it works, the only thing that needs to be thought of is to use a different variable name/prefix (e.g. "APP_...") so vite doesn't change them at build time.
I created a config file wich resolves the variable, for example if the app is in production than it uses the new Variable "APP_.."(which comes injected from nginx/ docker) or use "VITE_..."-variable if "APP_.." is undefined.
I came up with a solution and published it as packages to the npm registry.
With this solution, you don't need to change any code:
// src/index.js
console.log(`API base URL is: ${import.meta.env.API_BASE_URL}.`);
It separate the build step out into two build step:
During production it will be statically replaced import.meta.env with a placeholder:
// dist/index.js
console.log(
`API base URL is: ${"__import_meta_env_placeholder__".API_BASE_URL}.`
);
You can then run the package's CLI anywhere to replace the placeholders with your environment variables:
// dist/index.js
console.log(
`API base URL is: ${{ API_BASE_URL: "https://httpbin.org" }.API_BASE_URL}.`
);
// > API base URL is: https://httpbin.org.
Here is the documentation site: https://iendeavor.github.io/import-meta-env/.
Feel free to provide any feedback.
First create .env file in project root,then define a variable in .env
e.g:VITE_APP_any = 'any'
and then add following line to vite.config.js :
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), ""); //this line
return {
.
.
.
For usage can use following line
import.meta.env.VITE_APP_any
Or
process.env.VITE_APP_any
here is the Dockerfile
FROM node:alpine3.14 AS buildJS
WORKDIR /var/www/html
COPY . .
RUN apk add --no-cache yarn \
&& yarn && yarn build
FROM nginx:stable-alpine
WORKDIR /var/www/html
COPY --from=buildJS /var/www/html/dist .
COPY ./docker/conf/nginx.conf /etc/nginx/conf.d/default.conf
COPY ./docker/conf/config.json /etc/nginx/templates/config.json.template
ENTRYPOINT []
CMD sleep 5 && mv /etc/nginx/conf.d/config.json config.json & /docker-entrypoint.sh nginx -g 'daemon off;'
I'm building the project in the first stage without any envs,
in the second stage I'm copying the files and then creating the config.json file based on envs that are passed at run time with envstub feature of nginx.
then from the project I called the config.json file and load the envs from there but be careful you can not import it because imports will be resolved at build time instead you have to get it with fetch or axios or any equivalents
You can set the variables in YAML format and update them accordingly as per your requirement.
Below is the sample YAML format which we use as a template:
#Set variables once
variables:
configuration: debug
platform: x64
steps:
#Use them once
- task: MSBuild#1
inputs:
solution: solution1.sln
configuration: $(configuration) # Use the variable
platform: $(platform)
#Use them again
- task: MSBuild#1
inputs:
solution: solution2.sln
configuration: $(configuration) # Use the variable
platform: $(platform)
Check this SO for more insights to understand environment variables hosted in azure web app
I have built a single-page weather app with React and Node.js but can't seem to get it to deploy to Heroku. So far, I have:
Created a new app on Heroku called weather-app-react-node
Logged into Heroku on the CLI
Run the command 'heroku git:remote -a weather-app-react-node' in my terminal
Added a Procfile with 'web: npm start' in it
Ran 'git add .', 'git commit -m "Pushed to heroku"', 'git push heroku master'
My terminal tells me it is deployed and waiting but when I click on the link, I get this error message:
SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.
I've tried to google it but can't seem to find anything relevant to my situation. Anyone know how to fix it?
heroku-site: https://weather-app-react-node.herokuapp.com/github: https://github.com/caseycling/weather-app
To deploy the React app to Heroku, I performed the following steps...
1. In your terminal, enter npm -v and node -v to get your npm and node version. In my case, my npm version is 6.14.1 & my node version is 12.13.0.
2. In package.json, add "main": "server.js", and "engines": { "npm": "6.14.1", "node": "12.13.0" }, under the "private" property. In your scripts property, add "heroku-postbuild": "npm install" and set "start" to "node server.js".
3. In the root directory, create a Procfile with one line of text: web: node server.js.
4. In the root directory, create the server.js file with the below code..
const express = require("express");
// eslint-disable-next-line no-unused-vars
// const bodyParser = require('body-parser');
const path = require("path");
const app = express();
const port = process.env.PORT || 8080;
app.use(express.static(path.join(__dirname, "build")));
// This route serves the React app
app.get('/', (req, res) => res.sendFile(path.resolve(__dirname, "build", "index.html")));
app.listen(port, () => console.log(`Server listening on port ${port}`));
5. Enter npm run build in the terminal to produce the build directory. Next, remove (or comment out) /build from .gitignore file (in root directory).
6. Test if server.js works by entering node server.js (or nodemon server.js) in the terminal. If it works, server.js should serve the React app.
7. Commit everything from step 1-6 to GitHub and Heroku repository. To commit to Heroku repository, in your terminal, enter heroku git:remote -a weather-app-react-node and afterward, enter git push heroku master.
You can try logging in to heroku directly and deploy your github repository's desired branch from there directly.
I used create-react-app-buildpack
npm install -g create-react-app
create-react-app my-app
cd my-app
git init
heroku create -b https://github.com/mars/create-react-app-buildpack.git
or
heroku create -b mars/create-react-app
git add .
git commit -m "I am the newborn app"
git push heroku master
heroku open
Note: In my case, buildpack config from CLI did not work, I still had nodejs-build pack, so I manually changed the build pack to mars/create-react-app in the Heroku project dashboard
The best practice to push React apps to Heroku with a node js backend is to use the Heroku Post Build Script, The post build will take care of all the work under the hood
Follow the steps below
Add This below snippet to your package.json under the scripts
scripts{
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix reactFolderName && npm run build --prefix reactFolderName"
}
And add this snippet to your index.js file
app = express()
app.use(express.static('reactFolderName/build'));
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, 'reactFolderName', 'build', 'index.html')));
After I set up the all the things above mentioned I'm facing this issue.
When I'm using the URL like http://localhost:8080/ & http://localhost:8080/button
Cannot GET /button
In Console
Failed to load resource: the server responded with a status
of 404 (Not Found)
DevTools failed to load source map: Could not load content
for chrome-
extension://gighmmpiobklfepjocnamgkkbiglidom/browser-
polyfill.js.map: System error: net::ERR_FILE_NOT_FOUND
I am building a SPA in Angular 8. I have a multi-stage Docker image that runs ng build to build the distribution and then a simple express server is used to serve the application. (Note: The backend API is on an entirely separate express server.)
Requirements
I need to setup a login page "outside" of the SPA. The login page must be displayed if the user is not authenticated, that way the SPA is not bootstrapped until the authentication is successful (by checking a bearer token in the authorization header).
Questions
Do I need a separate Angular installation to load the login page separate from the rest of the app? Or, should I just skip Angular for the login page and build a simple express page with Pug that sends a POST to the API for authentication?
Note: I am seeking general advice on how to proceed and any examples would be very helpful as well.
Dockerfile
### Dev, QA, and Production Docker servers ###
### Stage 1: Build ###
# Base image
FROM node:12 as builder
# Set working directory
RUN mkdir -p /home/angular/app
WORKDIR /home/angular/app
# Add `/home/angular/app/node_modules/.bin` to $PATH
ENV PATH /home/angular/app/node_modules/.bin:$PATH
# Install and cache app dependencies
COPY angular/package.json /home/angular/app/package.json
RUN npm install -g #angular/cli#8 \
&& npm install
# Add app
COPY ./angular /home/angular/app
# Generate build
RUN ng build --output-path=dist
### Stage 2: Server ###
FROM node:12
USER node
# Create working directory
RUN mkdir /home/node/app
## From 'builder' stage copy over the artifacts in dist folder
COPY --from=builder --chown=node /home/angular/app/dist /home/node/app/dist
# Copy Express server code to container
COPY --chown=node ./express /home/node/app
WORKDIR /home/node/app
RUN npm install
# Expose ports
EXPOSE 4201
CMD ["npm", "start"]
Express server for Angular SPA
This server is run when the Dockerfile executes its command CMD ["npm", "start"]
const express = require('express');
const http = require('http');
const app = express();
// Set name of directory where angular distribution files are stored
const dist = 'dist';
// Set port
const port = process.env.PORT || 4201;
// Serve static assets
app.get('*.*', express.static(dist, { maxAge: '1y' }));
// Serve application paths
app.all('*', function (req, res) {
res.status(200).sendFile(`/`, { root: dist });
});
// Create server to listen for connections
const server = http.createServer(app);
server.listen(port, () => console.log("Node Express server for " + app.name + " listening on port " + port));
Angular supports multiple applications under same project. You can create separate login application using following command:
ng generate application <you-login-app-name-here>
This way you can keep only login related code in '' and other code in you main app. You can build, test or run this new app separate using following commands:
ng build <you-login-app-name-here>
ng test <you-login-app-name-here>
ng serve <you-login-app-name-here>
Angular will generate the build output in /dist/ folder which can be mapped to express route to serve file.
I am new to docker, I have successfully installed docker on ubuntu,
I am testing a node app, at folder: /home/samir/Documents/docker-centos:
$ ls
Dockerfile Dockerfile~ index.js index.js~ package.json package.json~
I don't know what are those duplicates ending with ~ as I didn't add them.
index.js:
var express = require('express');
// Constants
var PORT = 8080;
// App
var app = express();
app.get('/', function (req, res) {
// even if I change the output here, I still get Hello world only
res.send('Hello world, This was added\n');
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
Although I have started the container using a data volume that points to the same app dir like this:
docker run -p 49160:8080 -v /home/samir/Documents/docker-centos -d samir/centos-node-hello
but when I view the output like:
curl -i localhost:49160
I get Hello world even if I changed the file..
Do I miss something?
How would I run the container, and edit files at host? why it didn't work?
EDIT
Dockerfile
FROM centos:centos6
# Enable Extra Packages for Enterprise Linux (EPEL) for CentOS
RUN yum install -y epel-release
# Install Node.js and npm
RUN yum install -y nodejs npm
# Install app dependencies
COPY package.json /src/package.json
RUN cd /src; npm install
# Bundle app source
COPY . /src
EXPOSE 8080
CMD ["node", "/src/index.js"]
You need to build the Docker image again using the docker build command
If you're planning on using this setup not only for one-off testing of your app, but for development as well, you'd be better off mounting your application code as a volume.