使用docker-compose在运行时将环境变量传递给Vue.js应用程序

时间:2020-01-13 19:01:06

标签: docker vue.js docker-compose

这是我关于此特定问题的第二篇文章。此后,我删除了该问题,因为我找到了一种更好的方式来解释我到底想做什么。

基本上,我想将命令行参数传递给docker-compose up并将其设置为Vue.js Web应用程序中的环境变量。目标是能够更改环境变量,而无需每次都重新构建容器。

我遇到了一些问题。这是我的Docker文件:

适用于Vue.js应用程序的Dockerfile。

FROM node:latest as build-stage
WORKDIR /app

# Environment variable.
ENV VUE_APP_FOO=FOO

COPY package*.json ./
RUN npm install
COPY ./ .
RUN npm run build

FROM nginx as production-stage
RUN mkdir /app
COPY --from=build-stage /app/dist /app
COPY nginx.conf /etc/nginx/nginx.conf

VUE_APP_FOO可以通过Node的process.env对象进行存储和访问,并且似乎是在构建时传递的。

还有我的docker-compose.yml:

version: '3.5'

services:
    ms-sql-server:
        image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu
        ports: 
            - "1430:1433"
    api:
        image: # omitted (pulled from url)
        restart: always
        depends_on: 
            - ms-sql-server
        environment:
            DBServer: "ms-sql-server"
        ports:
            - "50726:80"
    client:
        image: # omitted(pulled from url)
        restart: always
        environment:
            - VUE_APP_BAR="BAR"
        depends_on: 
            - api
        ports:
            - "8080:80"

当我用docker exec -it <container_name> /bin/bash放入客户端容器时,VUE_APP_BAR变量的值为“ BAR”。但是变量没有存储在我的Vue应用程序的process.env对象中。 Node和环境变量似乎正在发生一些奇怪的事情。就像忽略了容器环境一样。

我是否仍然可以访问Vue.js应用程序内部docker-compose.yml中设置的容器级别变量?此外,是否有任何通过docker-compose up将这些变量作为参数传递的方法?让我知道您是否需要任何澄清/更多信息。

4 个答案:

答案 0 :(得分:2)

客户端应用程序在Web浏览器上运行,但是环境变量在服务器上。客户端需要一种从服务器获取环境变量值的方法。

要做到这一点,您有几种选择,包括:

  1. 利用Nginx来使用环境变量本身,例如以下一种方法:nginx: use environment variables。根据您的需求,此方法可能更快速,更动态或更静态,或者不太正式和不太优雅。或者

  2. 实现服务器API(Node.js?),该API读取环境变量并将其通过AJAX调用返回给客户端。这种方法优雅,动态,以API为中心。或者

  3. 最后,如果每个部署的每个nginx实例的环境变量都是静态的,则可以在部署过程中构建Vue应用程序的静态资产,然后在静态资产中将环境变量硬编码。这种方法虽然有些优雅,但确实会污染服务器详细信息的客户端代码,并且有些静态(只能在部署时更改)。

答案 1 :(得分:1)

正如我在此处https://stackoverflow.com/a/63097312/4905563上发布的那样,我开发了一个可以提供帮助的软件包。

尝试使用npm install jvjr-docker-env来看看README.md,以查看一些用法示例。

答案 2 :(得分:0)

因此,我弄清楚了如何以一种适合我的用例的完美方式进行此操作。我要做什么的快速回顾:能够通过docker-compose文件将环境变量传递到Vue.js应用程序,以允许不同的团队成员根据他们的分配来测试不同的开发API(如果在本地运行服务器,则为本地主机) ,api-dev,api-staging,api-prod)。

第一步是在VueJS项目(可以在任何地方定义)的JS文件中声明变量,格式如下:

export const serverURL = 'VUE_APP_SERVER_URL'

有关此字符串的值的快速说明:它对于整个项目必须是完全唯一的。如果您的应用程序中还有其他与之匹配的字符串或变量名,将被使用此方法传递的docker环境变量替换。

接下来,我们必须转到docker-compose.yml并在其中声明我们的环境变量:

docker-compose.yml

your_vuejs_client:
    build: /path/to/vuejs-app
    restart: always
    environment: 
        VUE_APP_SERVER_URL: ${SERVER_URL}
    ports:
        - "8080:80"

现在,当您在终端中运行docker-compose up时,应该看到类似以下内容: WARNING: The SERVER_URL variable is not set. Defaulting to a blank string.

在正确设置了docker-compose设置之后,我们需要在VueJS应用程序中创建一个入口点脚本才能运行,然后再通过nginx启动该应用程序。为此,请导航回到您的VueJS目录并运行touch entrypoint.sh以创建空白bash脚本。打开它,这就是我拥有的:

entrypoint.sh

#!/bin/sh

ROOT_DIR=/usr/share/nginx/html

echo "Replacing env constants in JS"
for file in $ROOT_DIR/js/app.*.js* $ROOT_DIR/index.html $ROOT_DIR/precache-manifest*.js;
do
  echo "Processing $file ...";

  sed -i 's|VUE_APP_SERVER_URL|'${VUE_APP_SERVER_URL}'|g' $file

done

sed -i 's|VUE_APP_SERVER_URL|'${VUE_APP_SERVER_URL}'|g' $file这行代码将整个应用程序扩展为字符串'VUE_APP_SERVER_URL',并将其替换为docker-compose.yml中的环境变量。

最后,我们需要在VueJS应用程序Dockerfile中添加一些行,以使其运行在nginx启动之前刚创建的入口点脚本。因此,在Dockerfile中的CMD ["nginx", "-g", "daemon off;"]行之前,添加以下行:

VueJS Dockerfile

# Copy entrypoint script as /entrypoint.sh
COPY ./entrypoint.sh /entrypoint.sh

# Grant Linux permissions and run entrypoint script
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

在那之后,运行docker-compose run -e SERVER_URL=yourserverapi.com/api,我们在开始时在JS文件中设置的serverURL常量将被您在docker-compose命令中提供的内容替换。最终上班很痛苦,但是我希望这可以帮助遇到类似麻烦的任何人。很棒的是,您可以根据需要添加任意数量的环境变量,只需在entrypoint.sh文件中添加更多行,然后在Vue.js应用程序和docker-compose文件中对其进行定义。我使用过的一些工具为USPS API提供了不同的终结点,具体取决于您是本地运行还是托管在云中;根据实例是在生产环境中还是在开发环境中运行,提供不同的Maps API密钥。等

我真的希望这可以帮助某人,让我知道是否有人有任何疑问,希望能对您有所帮助。

答案 3 :(得分:0)

尽管问题标题说的是如何从 vue.js 端使用环境变量,但提问者的目标是能够在不重建 docker 镜像的情况下动态配置后端 api 端点。

我是通过反向代理实现的。

  1. 对于开发运行,请在 vue.config.js 上配置反向代理,由 vue-cli Web 服务器使用。
  2. 对于 nginx 运行,在 nginx.conf 上配置反向代理。 You can use nginx template to read environment variables

这种方法还消除了在 web-api 服务器端配置 CORS 的需要,因为 web api 是从 vue 应用程序的 web 服务器调用的,而不是直接从浏览器调用。

可以在 this commit.

上找到更全面的工作示例

vue.config.js:

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://host.docker.internal:5000',
      },
    },
  },
};

nginx.conf:

...
http {
  ...
  include /etc/nginx/conf.d/*.conf;
}

nginx.default.conf.template:

  server {
    listen       80;
...
    location /api {
      proxy_pass ${WEBAPI_ENDPOINT};
    }
  }

Dockerfile:

...
COPY nginx.conf /etc/nginx/nginx.conf
COPY nginx.default.conf.template /etc/nginx/templates/default.conf.template