VueCLI3 应用程序 (nginx/docker) 使用环境特定变量
VueCLI3 app (nginx/docker) use environment specific variables
如何从 Vue 应用程序外部化 和使用 环境变量:
- 创建于 VueCLI3
- 部署在 docker 容器中
- 使用 NGINX
一些细节:
项目构建一次并部署到测试和实际环境。因此,我想外部化一些变量,这些变量 通过环境 发生变化(例如要调用的 URL、域、用户名等)。带有 VUE_APP_
前缀的 .env
文件变体的经典用法无助于解决此问题,因为它们的值是在构建阶段注入到代码中的:它们一旦构建就不是变量。
试了一下,我发现了一个blog post making use of dotenv
and some extra configuration; but I could not put it together with the configuration in this VueCLI 3 official guide。虽然解决方案不需要采用类似的方法,但我只是想出一条路。
可能不是有用的信息,但我打算在 Kubernetes 配置中的 Config Maps 中定义这些环境变量。
我想我已经完成了这个案子。我在这里留下决议。
在 .env.development
中定义特定于环境的环境变量(用于开发目的),并将它们也添加到具有相应值的 Pod configuration 中。
在您的 Vue 项目源文件夹中的某处添加一个 configuration.js
文件。它将充当确定运行时是开发(本地)还是生产(容器)的包装器。就像显示的 here,但 importing/configuring 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
}
}
创建一个 entrypoint.sh
。经过一些修改,它看起来像这样:
#!/bin/bash
function join_by { local IFS=""; shift; echo "$*"; }
# Find vue env vars
vars=$(env | grep VUE_APP_ | awk -F = '{print "$"}')
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;'
在您的 Dockerfile
中,为 运行 添加一个 CMD
上面的 entrypoint.sh
脚本 作为容器期间的引导脚本创作。这样,每次启动容器时,它都会从 pod 配置中获取环境变量,并将其注入 步骤 2.[=24= 中显示的配置 class ]
# 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')
一样使用我们的包装器配置 class 而不是 process.env
。瞧!
如何从 Vue 应用程序外部化 和使用 环境变量:
- 创建于 VueCLI3
- 部署在 docker 容器中
- 使用 NGINX
一些细节:
项目构建一次并部署到测试和实际环境。因此,我想外部化一些变量,这些变量 通过环境 发生变化(例如要调用的 URL、域、用户名等)。带有 VUE_APP_
前缀的 .env
文件变体的经典用法无助于解决此问题,因为它们的值是在构建阶段注入到代码中的:它们一旦构建就不是变量。
试了一下,我发现了一个blog post making use of dotenv
and some extra configuration; but I could not put it together with the configuration in this VueCLI 3 official guide。虽然解决方案不需要采用类似的方法,但我只是想出一条路。
可能不是有用的信息,但我打算在 Kubernetes 配置中的 Config Maps 中定义这些环境变量。
我想我已经完成了这个案子。我在这里留下决议。
在
.env.development
中定义特定于环境的环境变量(用于开发目的),并将它们也添加到具有相应值的 Pod configuration 中。在您的 Vue 项目源文件夹中的某处添加一个
configuration.js
文件。它将充当确定运行时是开发(本地)还是生产(容器)的包装器。就像显示的 here,但 importing/configuringdotenv
不是必需的: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 } }
创建一个
entrypoint.sh
。经过一些修改,它看起来像这样:#!/bin/bash function join_by { local IFS=""; shift; echo "$*"; } # Find vue env vars vars=$(env | grep VUE_APP_ | awk -F = '{print "$"}') 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;'
在您的
Dockerfile
中,为 运行 添加一个CMD
上面的entrypoint.sh
脚本 作为容器期间的引导脚本创作。这样,每次启动容器时,它都会从 pod 配置中获取环境变量,并将其注入 步骤 2.[=24= 中显示的配置 class ]# 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')
一样使用我们的包装器配置 class 而不是 process.env
。瞧!