VueCLI3 app (nginx/docker) use environment specific variables VueCLI3 app (nginx/docker) use environment specific variables nginx nginx

VueCLI3 app (nginx/docker) use environment specific variables


I think I've accomplished to overcome this case. I am leaving the resolution here.

  1. Define your environment-specific environment variables in .env.development (for development purposes) and add them also to the Pod configuration with correxponding values.

  2. Add a configuration.js file somewhere in your Vue project source folder. It would act as a wrapper for determining whether the runtime is development (local) or production (container). It is like the one shown here, but importing/configuring dotenv is not required:

    export default class Configuration {  static get EnvConfig () {    return {      envKey1: '$ENV_KEY_1',      envKey2: '$ENV_KEY_2'    }  }  static value (key) {    // If the key does not exist in the EnvConfig object of the class, return null    if (!this.EnvConfig.hasOwnProperty(key)) {      console.error(`Configuration: There is no key named "${key}". Please add it in Configuration class.`)      return    }    // Get the value    const value = this.EnvConfig[key]    // If the value is null, return    if (!value) {      console.error(`Configuration: Value for "${key}" is not defined`)      return    }    if (!value.startsWith('$VUE_APP_')) {      // value was already replaced, it seems we are in production (containerized).      return value    }    // value was not replaced, it seems we are in development.    const envName = value.substr(1) // Remove $ and get current value from process.env    const envValue = process.env[envName]    if (!envValue) {      console.error(`Configuration: Environment variable "${envName}" is not defined`)      return    }    return envValue  }}
  3. Create an entrypoint.sh. With some modification, it would look like follows:

    #!/bin/bashfunction join_by { local IFS="$1"; shift; echo "$*"; }# Find vue env varsvars=$(env | grep VUE_APP_ | awk -F = '{print "$"$1}')vars=$(join_by ',' $vars)echo "Found variables $vars"for file in /app/js/app.*;do  echo "Processing $file ...";  # Use the existing JS file as template  cp $file $file.tmpl  envsubst "$vars" < $file.tmpl > $file  rm $file.tmpldonenginx -g 'daemon off;'
  4. In your Dockerfile, add a CMD for running this entrypoint.sh script above as a bootstrapping script during container creation. So that, every time you start a container, it will get the environment variables from the pod configuration and inject it to the Configuration class shown in Step 2.

    # build stageFROM node:lts-alpine as build-stage# make the 'app' folder the current working directoryWORKDIR /app# Copy package*.json and install dependencies in a separaate step to enable cachingCOPY package*.json ./RUN npm install# copy project files and folders to the current working directoryCOPY ./ .# install dependencies and build app for production with minificationRUN npm run build# Production stageFROM nginx as production-stageRUN mkdir /app# copy 'dist' content from the previous stage i.e. buildCOPY --from=build-stage /app/dist /app# copy nginx configurationCOPY nginx.conf /etc/nginx/nginx.conf# Copy the bootstrapping script to inject environment-specific values and pass it as argument current to entrypointCOPY entrypoint.sh entrypoint.sh# Make the file executableRUN chmod +x ./entrypoint.shCMD ["./entrypoint.sh"]

Finally, instead of process.env use our wrapper configuration class like Configuration.value('envKey1'). And voila!