尝试在AWS / EBS(Amazon Web Services,Elastic Beanstalk)环境中设置Meteor。
Meteor dev-run可以传递命令行标志:--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" } }
问题是当我在EBS控制台中将METEOR_SETTINGS
的值设置为此值时:
AWS / EBS丢弃引号,转义斜杠(如屏幕截图所示),然后发送Meteor:
{public:{s3path:https:\/\/d2v4p3rms9rvi3.cloudfront.net}}
如节点启动错误所示:
-------------------------------------
/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
碰到这个问题我在值字段中尝试了JSON对象的各种变体: 转义引号,用单引号括起整个json部分,用单引号替换双引号,以及其他尝试 - 都没有解决它。
问题是:
如何设置METEOR_SETTINGS
以便Meteor rcv&正确解析它?
注意:其中一个要求是相同的构建部署到开发,登台和生产环境。需要为每个环境单独设置配置,因此,如果有另一种方法将设置注入EBS环境,而不修改也将解决它的构建。
答案 0 :(得分:2)
在使用AWS支持讨论此问题后,我意识到AWS / EBS不支持在环境变量中存储JSON。这是因为环境变量在未编码的JSON中存储为键/值字符串(显然,在CloudFormation中)。这里的底线有点令人失望:
这确实很不幸,但有一些解决方法。
将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
这将完全覆盖从您的s3存储桶中检索到的内容/etc/init/nodejs.conf
。当然,有机会使用微调/花哨的bash脚本来设置/覆盖个别设置。
我最终没有选择这种方法,因为它涉及另一个实体(一个S3存储桶),而开发迭代需要一个新版本的部署,这个速度并不快。
注意:这是我想出的一个简单的代码破解。它似乎把所有这些混乱放在一边,而不需要太多的努力。
我最初的需求是将AWS / EBS env变量传播到客户端,因此我决定绕过METEOR_SETTINGS
变量并直接使用来自节点{{1的env变量'填充Meteor.settings.public
}} 空间。白名单由简单列表管理。添加process.env
文件:
server/lib/config.js
Hurray,您的客户可以访问您选择的env vars!
例如,通过此更改,可以在客户端上以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;
}
});
访问EBS控制台中定义的S3_PATH环境变量。非常简单,没有很多活动部件:)
答案 1 :(得分:1)
测试了另一种解决方法。
meteor build --directory
后的
编辑main.js
如下
process.argv.splice(2, 0, 'program.json');
var settingfilename = './settings.json';
if (process.env.METEOR_SETTING_FILE)
settingfilename = process.env.METEOR_SETTING_FILE;
var settings = require(settingfilename);
if (settings) {
try {
process.env.METEOR_SETTINGS = JSON.stringify(settings);
} catch (e) {
console.error(e);
}
}
process.chdir(require('path').join(__dirname, 'programs', 'server'));
require('./programs/server/boot.js');
并将settings.json
复制到bundle/
和eb init
以及eb deploy
。
您可以通过在EB控制台的“配置”选项卡中的“环境属性”中添加METEOR_SETTING_FILE
来设置其他设置文件。
编辑文件。
添加了补丁文件,以便在ed - ../build/bundle/main.js < main.js.patch
main.js.patch
8a
var settingfilename = './settings.json';
if (process.env.METEOR_SETTING_FILE)
settingfilename = process.env.METEOR_SETTING_FILE;
var settings = require(settingfilename);
if (settings) {
try {
process.env.METEOR_SETTINGS = JSON.stringify(settings);
} catch (e) {
console.error(e);
}
}
// console.log (JSON.stringify(process.env));
.
w
答案 2 :(得分:1)
新解决方案
这是我能够更轻松的方式。我已经创建了一个bash脚本,可以自动生成项目的压缩版本并集成设置文件,因此您不需要做任何事情。
在运行此脚本之前
在你的meteor项目中创建./lib/beanstalk-settings-fix.js
/*==============================================================================
* Globals
*============================================================================*/
/*global process*/
/*global Meteor*/
/*global Npm*/
if (Meteor.isProduction){
var meteorFile = process.env.METEOR_SETTINGS_FILE;
if(meteorFile == undefined) throw new Error(
'METEOR_SETTINGS_FILE env variable must be defined in production.')
var fs = Npm.require('fs');
var pjsonBuf = fs.readFileSync( meteorFile );
Meteor.settings = JSON.parse( pjsonBuf.toString().trim());
}
如何使用
你将以project-name.zip之类的东西结束,准备将它上传到你的beanstalk环境。我希望你觉得它很有用!
此解决方案基于AWS forums。如果您想查看旧解决方案,请查看编辑历史记录。
#!/bin/bash
#===============================================================================
# DESCRIPTION:
#===============================================================================
# This script creates a build of the project ready to be uploaded to beanstalk.
# Requires pyton 2.7.x
#===============================================================================
# COMMON ISSUES:
#===============================================================================
# -If you upload the output to a sample application, it will fail.
# -Version format must be 0.0.0
#===============================================================================
# CONSTANTS
#===============================================================================
CURRENT_VERSION="1.0.0"
OUTPUT_NAME="file-name-without-extension"
PRODUCTION_SETTINGS_JSON="./your-project-directory/settings-prod.json"
PROJECT_DIRECTORY="./your-project-directory"
OUTPUT_DIRECTORY="./the-output-directory"
ROOT_URL="http://www.SOMEENVIRONMENT-env.us-west-2.elasticbeanstalk.com"
MONGO_URL="none"
#===============================================================================
# SAY HELLO
#===============================================================================
initial_directory=$(pwd) # This file's local path
clear
echo "COOKING OUTPUT"
echo "========================================================="
#===============================================================================
# RAW PROJECT BUILD
#===============================================================================
echo "> BUILDING RAW PROJECT"
cd $initial_directory
cd $PROJECT_DIRECTORY
rm -f -R "../build/bundle"
meteor build --directory ../build/
#===============================================================================
# SET PRODUCTION ENVIRONMENT VARIABLES
#===============================================================================
cd $initial_directory
json=`cat $PRODUCTION_SETTINGS_JSON`
cd $OUTPUT_DIRECTORY/bundle
mkdir -p .ebextensions
echo "option_settings:" >> .ebextensions/environment.config
echo " - option_name: MONGO_URL" >> .ebextensions/environment.config
echo " value: $MONGO_URL" >> .ebextensions/environment.config
echo "option_settings:" >> .ebextensions/environment.config
echo " - option_name: ROOT_URL" >> .ebextensions/environment.config
echo " value: "$ROOT_URL"" >> .ebextensions/environment.config
echo "files:" >> .ebextensions/environment.config
echo " '/tmp/settings.json':" >> .ebextensions/environment.config
echo " content : |" >> .ebextensions/environment.config
echo " "$json >> .ebextensions/environment.config
echo "option_settings:" >> .ebextensions/environment.config
echo " - namespace: aws:elasticbeanstalk:application:environment" >> .ebextensions/environment.config
echo " option_name: METEOR_SETTINGS_FILE" >> .ebextensions/environment.config
echo " value: '/tmp/settings.json'" >> .ebextensions/environment.config
chmod 444 .ebextensions/environment.config
echo "> ADDING 'settings.json' AS ENV VAR"
#===============================================================================
# CREATE PACKAGE.JSON
#===============================================================================
cd $initial_directory
cd $OUTPUT_DIRECTORY/bundle
# Write base package.json
echo '{
"name": "'$OUTPUT_NAME'",
"version": "'$CURRENT_VERSION'",
"scripts": {
"start": "node main.js"
},
"dependencies": {
}
}' > ./package.json
# Add dependencies from meteor in packages.json
# Then add extra dependencies defined by us.
EXTRA_DEPENDENCIES='{"forever": "*"}'
meteor_packages=$(cat ./programs/server/package.json)
packages=$(cat ./package.json)
packages_updated=`python <<END
import json;
# We cannot operate directly bash variables, so we make a copy.
a = $packages
b = $meteor_packages
a['dependencies'] = b['dependencies']
for key, value in $EXTRA_DEPENDENCIES.iteritems():
a['dependencies'].update({key: value})
print json.dumps(a, sort_keys=False, indent=4, separators=(',', ': '));
END`
echo "$packages_updated" > ./package.json
chmod 444 ./package.json
echo "> ADDING 'package.json'"
#===============================================================================
# ZIP OUTPUT
#===============================================================================
cd $initial_directory
cd $OUTPUT_DIRECTORY/bundle
zip -FSrq "../$OUTPUT_NAME-$CURRENT_VERSION.zip" .
echo "> ZIP THE OUTPUT"
#===============================================================================
# CLEAN THE HOUSE
#===============================================================================
cd $initial_directory
cd $OUTPUT_DIRECTORY
rm -R -f ./bundle
echo "> CLEAN THE HOUSE"
#===============================================================================
# SAY GOODBYE
#===============================================================================
echo "========================================================="
echo "YOU CAN UPLOAD THE PROJECT TO A BEANSTALK ENVIRONMENT NOW"
一些额外的帮助:如果您想检查一切正常,您可以在/ebextensions/environment.config下的压缩输出中找到最终设置,并在/下的/的package.json