如何使用METEOR_SETTINGS环境变量在AWS/EBS上配置Meteor

tiv*_*oni 8 amazon-web-services meteor amazon-elastic-beanstalk

尝试在AWS/EBS(Amazon Web Services,Elastic Beanstalk)环境中设置Meteor.

Meteor开发运行可以传递命令行标志:--settings settings.json 其中settings.json 是包含服务器/客户端键/值配置的文件(作为格式正确的JSON).

Meteor的部署使用METEOR_SETTINGS环境变量,而不是在命令行中传递配置文件.如果提供的话,它应该包含一个json文档settings.json,例如:

$ METEOR_SETTINGS=$(cat settings.json)
$ echo $METEOR_SETTINGS
{ "public": { "s3path": "https://d2v4p3rms9rvi3.cloudfront.net" } }
Run Code Online (Sandbox Code Playgroud)

问题是当我METEOR_SETTINGS在EBS控制台中将值设置为此值时:

(截图)

AWS/EBS丢弃引号,转义斜杠(如屏幕截图所示),并发送Meteor:

{public:{s3path:https:\/\/d2v4p3rms9rvi3.cloudfront.net}}
Run Code Online (Sandbox Code Playgroud)

如节点启动错误所示:

-------------------------------------
/var/log/nodejs/nodejs.log
-------------------------------------
npm WARN deprecated backwards-incompatible changes made to `npm run-script` and
npm WARN deprecated semver behavior.

> meteor-dev-bundle@0.0.0 start /var/app/current
> node main.js


/var/app/current/programs/server/boot.js:283
}).run();
   ^
Error: METEOR_SETTINGS are not valid JSON: {public:{s3path:https:\/\/d2v4p3rms9rvi3.cloudfront.net}}
    at packages/meteor/packages/meteor.js:21:1
    at Package (packages/meteor/packages/meteor.js:42:1)
    at /var/app/current/programs/server/packages/meteor.js:1277:4
    at /var/app/current/programs/server/packages/meteor.js:1286:3
    at /var/app/current/programs/server/boot.js:242:10
    at Array.forEach (native)
    at Function._.each._.forEach (/var/app/current/node_modules/underscore/underscore.js:79:11)
    at /var/app/current/programs/server/boot.js:137:5
Run Code Online (Sandbox Code Playgroud)

碰到这个问题我在值字段中尝试了JSON对象的各种变体:转义引号,用单引号括起整个json部分,用单引号替换双引号,以及其他尝试 - 都没有解决它.

问题是:

如何METEOR_SETTINGS设置Meteor rcv并正确解析它?

注意:其中一个要求是相同的构建部署到开发,登台和生产环境.需要为每个环境单独设置配置,因此如果有另一种方法将设置注入到EBS环境中,而不修改也将解决它的构建.

tiv*_*oni 3

在与 AWS 支持人员讨论这个问题后,我意识到 AWS/EBS 不支持在环境变量中存储 JSON。这是因为环境变量以键/值字符串的形式存储在未编码的 JSON 中(显然是在 CloudFormation 中)。这里的底线有点令人失望:

METEOR_SETTINGS 无法在 AWS/EBS 控制台中使用

这确实很不幸,但是有一些解决方法。

第一个解决方法

将 json 配置移至 s3 存储桶并将以下内容放入文件中.ebextensions/app.config

container_commands: 
  01_setvariable: 
    command: "aws s3 cp s3://<bucket-name>/nodejs.conf /tmp/deployment/config/#etc#init#nodejs.conf 
Run Code Online (Sandbox Code Playgroud)

这将完全覆盖/etc/init/nodejs.conf从您的 s3 存储桶检索的内容。当然,有机会使用微调/花哨的 bash 脚本来设置/覆盖各个设置。

我最终没有选择这种方法,因为它涉及另一个实体(S3 存储桶),并且开发迭代需要新版本部署,这不是很快。

第二种解决方法

注意:这是我想出的一个简单的代码破解。似乎不需要太多努力就能把所有这些混乱抛在脑后。

我最初的需求是将 AWS/EBS 环境变量传播到客户端,因此我决定绕过该METEOR_SETTINGS变量并Meteor.settings.public直接使用节点process.env空间中的环境变量进行填充。白名单由一个简单的列表管理。添加一个server/lib/config.js文件:

Meteor.startup(function () {
    // public settings that need to be exposed to the client can be added here
    var publicEnvs = {
        S3_PATH: 's3path'
    };
    var modified;
    _.each(publicEnvs, (value, key) => {
        let envValue = process.env[key];
        if (envValue) {
            Meteor.settings.public[value] = envValue;
            modified = true;
        }
    });
    if (modified) {
        __meteor_runtime_config__.PUBLIC_SETTINGS = Meteor.settings.public;
    }
});
Run Code Online (Sandbox Code Playgroud)

万岁,您的客户可以访问您选择的环境变量!

例如,通过此更改,可以像Meteor.settings.public.s3path在客户端上一样访问 EBS 控制台中定义的 S3_PATH 环境变量。非常简单,并且没有很多活动部件:)