docker - VueCLI3 应用程序 (nginx/docker) 使用环境特定变量

标签 docker vue.js nginx environment-variables vue-cli-3

如何从 Vue 应用程序外部化使用环境变量:

  • 创建于 VueCLI3
  • 部署在 Docker 容器中
  • 使用 NGINX

一些细节:

该项目构建一次并部署到测试和实时环境。因此,我想外部化一些随环境变化的变量(例如要调用的 URL、域、用户名等)。带有 VUE_APP_ 前缀的 .env 文件变体的经典用法无助于解决此问题,因为它们的值在构建阶段注入(inject)到代码中:一旦成为变量,它们就不再是变量。已建成。

尝试了一下,我发现了一个blog post利用 dotenv 和一些额外的配置;但我无法将其与 this VueCLI 3 official guide 中的配置放在一起。不过解决方案并不需要采用类似的方法,我只是想找到一条出路。

可能不是有用的信息,但我计划在 Config Maps 中定义这些环境变量在 Kubernetes 配置中。

最佳答案

我想我已经成功克服了这个问题。我将决议留在这里。

  1. .env.development 中定义特定于环境的环境变量(用于开发目的),并将它们也添加到 Pod configuration具有相应的值。

  2. 在 Vue 项目源文件夹中的某个位置添加一个 configuration.js 文件。它将充当包装器,用于确定运行时是开发(本地)还是生产(容器)。就像显示的那样 here ,但不需要导入/配置 dotenv:

    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. 创建一个entrypoint.sh。经过一些修改,它看起来如下:

    #!/bin/bash
    
    function join_by { local IFS="$1"; shift; echo "$*"; }
    
    # Find vue env vars
    vars=$(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.tmpl
    done
    
    nginx -g 'daemon off;'
    
  4. 在您的 Dockerfile 中,添加一个 CMD,用于在期间运行上面的 entrypoint.sh 脚本作为引导脚本容器创建。这样,每次启动容器时,它都会从 Pod 配置中获取环境变量,并将其注入(inject)到步骤 2 中所示的 Configuration 类中。

    # build stage
    FROM node:lts-alpine as build-stage
    
    # make the 'app' folder the current working directory
    WORKDIR /app
    
    # Copy package*.json and install dependencies in a separaate step to enable caching
    COPY package*.json ./
    RUN npm install
    
    # copy project files and folders to the current working directory
    COPY ./ .
    
    # install dependencies and build app for production with minification
    RUN npm run build
    
    # Production stage
    FROM nginx as production-stage
    
    RUN mkdir /app
    
    # copy 'dist' content from the previous stage i.e. build
    COPY --from=build-stage /app/dist /app
    
    # copy nginx configuration
    COPY nginx.conf /etc/nginx/nginx.conf
    
    # Copy the bootstrapping script to inject environment-specific values and pass it as argument current to entrypoint
    COPY entrypoint.sh entrypoint.sh
    
    # Make the file executable
    RUN chmod +x ./entrypoint.sh
    
    CMD ["./entrypoint.sh"]
    
    

最后,使用我们的包装器配置类(如 Configuration.value('envKey1'))代替 process.env。瞧!

关于docker - VueCLI3 应用程序 (nginx/docker) 使用环境特定变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57807248/

相关文章:

java - 如何为不同的 Zookeeper Docker 容器设置不同的管理端口?

docker - 已成功安装magento2,但未找到管理页面抛出错误

html - 粘性导航栏显示在所有 View 中

javascript - Vuejs 观察者命令

ubuntu - 此站点无法提供安全连接 ERR_SSL_PROTOCOL_ERROR

mongodb - Docker/Mongodb 数据不持久

Linux 网络 - Docker 容器通过网关到远程主机而不使用路由添加?

typescript - Vue TSX - 如何告诉 Typescript 在可重用组件中允许使用 HTML 属性?

linux - 如何在同一台服务器上显示另一个端口网站的nginx 80数据?

nginx - 将请求 header 变量作为查询参数传递给上游 URL