首页 文章

如何存储Node.js部署设置/配置文件?

提问于
浏览
582

我一直在研究一些Node应用程序,我一直在寻找一种存储部署相关设置的良好模式 . 在Django世界(我来自哪里),常见的做法是将 settings.py 文件包含标准设置(时区等),然后使用 local_settings.py 进行部署特定设置,即 . 要与哪个数据库交谈,什么是memcache套接字,管理员的电子邮件地址等等 .

我一直在寻找类似Node的模式 . 只是一个配置文件会很好,所以它不必与 app.js 中的其他所有内容一起使用,但我发现在一个不在源代码管理中的文件中设置特定于服务器的配置很重要 . 相同的应用程序可以在不同的服务器上部署,具有完全不同的设置,并且必须处理合并冲突以及所有这些不是我的乐趣 .

那么是否有某种框架/工具,或者每个人都自己一起破解某些东西?

23 回答

  • 225

    我刚刚使用的一个alt示例,因为我想要比典型的.json文件更灵活,但是不希望它被抽象到一个需要依赖的库中 . 基本上,导出一个立即调用的函数,该函数返回一个具有我想要的值的对象 . 提供了很大的灵活性 .

    module.exports = function(){
           switch(node_env){
             case 'dev':
               return
               { var1 = 'development'};
             }
        }();
    

    这里有完整的例子,有一个更好的解释 . Using Config Files in Node.js

  • 1

    您可以将Konfig用于特定于环境的配置文件 . 它自动加载json或yaml配置文件,它具有默认值和动态配置功能 .

    Konfig repo的一个例子:

    File: config/app.json
    ----------------------------
    {
        "default": {
            "port": 3000,
            "cache_assets": true,
            "secret_key": "7EHDWHD9W9UW9FBFB949394BWYFG8WE78F"
        },
    
        "development": {
            "cache_assets": false
        },
    
        "test": {
            "port": 3001
        },
    
        "staging": {
            "port": #{process.env.PORT},
            "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
        },
    
        "production": {
            "port": #{process.env.PORT},
            "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
        }
    }
    

    开发中:

    > config.app.port
    3000
    

    在 生产环境 中,假设我们用 $ NODE_ENV=production PORT=4567 node app.js 开始申请

    > config.app.port
    4567
    

    更多细节:https://github.com/vngrs/konfig

  • 23

    从Node v0.5.x(referencing this answer)开始,您可以要求JSON文件

    config.json:

    {
        "username" : "root",
        "password" : "foot"
    }
    

    app.js:

    var config = require('./config.json');
    log_in(config.username, config.password);
    
  • 3

    我刚刚发布了一个小模块来加载任何类型的配置文件 . 这很简单,您可以在https://github.com/flesler/config-node查看

  • 11

    你们是否使用npm来启动脚本(env等)?

    如果您使用 .env 文件,则可以将它们包含在 package.json 中并使用npm来源/启动它们 .

    例:

    {
      "name": "server",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "node test.js",
        "start-dev": "source dev.env; node test.js",
        "start-prod": "source prod.env; node test.js"
      },
      "dependencies": {
        "mysql": "*"
      }
    }
    

    然后运行npm脚本:

    $ npm start-dev
    

    它在这里描述https://gist.github.com/ericelliott/4152984所有归功于Eric Elliot

  • 0

    我要把帽子扔进戒指,因为这些答案都没有解决几乎任何系统需要的所有关键组件 . 注意事项:

    • 公共配置(前端可以看到)vs私人配置(家伙mograbi得到了这个权利) . 并确保这些是分开的 .

    • 像钥匙一样的秘密

    • 默认值与特定于环境的覆盖

    • 前端捆绑

    这是我如何配置:

    • config.default.private.js - 在版本控制中,这些是默认配置选项,只能由后端查看 .

    • config.default.public.js - 在版本控制中,这些是后端和前端可以看到的默认配置选项

    • config.dev.private.js - 如果您需要dev的不同私有默认值 .

    • config.dev.public.js - 如果您需要dev的不同公共默认值 .

    • config.private.js - 不在版本控制中,这些是覆盖 config.default.private.js 的特定于环境的选项

    • config.public.js - 不在版本控制中,这些是覆盖 config.default.public.js 的特定于环境的选项

    • keys/ - 每个文件存储某种不同秘密的文件夹 . 这也不受版本控制(密钥永远不应受版本控制) .

    我使用普通的javascript文件进行配置,因此我拥有javascript语言的全部功能(包括注释和执行操作的能力,例如在环境特定的文件中加载默认配置文件,以便可以覆盖它们) . 如果你想使用环境变量,你可以在这些配置文件中加载它们(因为我不建议使用json文件,因此我建议不要使用env变种 - 你没有编译语言的强大功能来构建你的配置) .

    每个密钥位于单独文件中的原因是供安装程序使用 . 这允许您拥有一个在机器上创建密钥的安装程序,并将它们存储在keys文件夹中 . 如果没有这个,加载无法访问密钥的配置文件时,安装程序可能会失败 . 这样,您可以遍历目录并加载该文件夹中的任何密钥文件,而无需担心代码的任何给定版本中存在什么和不存在什么 .

    由于您可能在私有配置中加载了密钥,因此您绝对不应该做两件事来阻止在前端加载私有配置:

    • 我有一个单元测试,确保我的前端包不包含私有配置中的一个密钥 .

    • 我的前端代码位于与后端代码不同的文件夹中,我有两个不同的文件名为"config.js" - 每端一个 . 对于后端,config.js加载私有配置,对于前端,它加载公共配置 . 然后你总是需要('config')并且不用担心它来自哪里 .

    最后一件事:您的配置应该通过 completely 单独的文件加载到浏览器中,而不是任何其他前端代码 . 如果捆绑前端代码,则应将公共配置构建为完全独立的捆绑包 . 否则,您的配置不再是真正的配置 - 它只是代码的一部分 . 配置需要能够在不同的机器上不同 .

  • 0

    exports 做一个简单的 settings.js

    exports.my_password = 'value'
    

    然后,在您的脚本中,执行 require

    var settings = require('./settings.js');
    

    您现在的所有设置都将通过 settings 变量提供:

    settings.my_password // 'value'
    
  • 11

    我知道这是一个非常古老的帖子 . 但我想分享我的模块来配置环境变量,我认为这是非常灵活的解决方案 . 这是模块json-configurator

    var configJson = {
      'baseUrl': 'http://test.com',
      '$prod_baseUrl': 'https://prod.com',
      'endpoints': {
        'users': '<%= baseUrl %>/users',
        'accounts': '<%= baseUrl %>/accounts'
        },
      foo: 'bar',
      foobar: 'foobar',
      $prod_foo: 'foo in prod',
      $test_foo: 'foo in test',
      deep:{
        veryDeep: {
          publicKey: 'abc',
          secret: 'secret',
          $prod_secret: 'super secret'
        }
      }
    };
    
    var config = require('json-configurator')(configJson, 'prod');
    
    console.log(config.deep.veryDeep.secret) 
    // super secret 
    
    console.log(config.endpoints.users)
    // https://prod.com/users
    

    然后,您可以使用 process.env.NODE_ENV 获取环境的所有变量 .

  • 30

    你可以使用pconf:https://www.npmjs.com/package/pconf

    例:

    var Config = require("pconf");
    var testConfig = new Config("testConfig");
    testConfig.onload = function(){
    
      testConfig.setValue("test", 1);
      testConfig.getValue("test");
      //testConfig.saveConfig(); Not needed
    
    }
    
  • 716

    最好将 'development''production' 配置分开 .

    我使用以下方式:这是我的 config/index.js 文件:

    const config = {
        dev : {
            ip_address : '0.0.0.0',
            port : 8080,
            mongo :{
                url : "mongodb://localhost:27017/story_box_dev",
                options : ""
            }
        },
        prod : {
            ip_address : '0.0.0.0',
            port : 3000,
            mongo :{
                url : "mongodb://localhost:27017/story_box_prod",
                options : ""
            }
        }
    }
    

    对于require,配置使用以下内容:

    const config = require('../config')[process.env.NODE_ENV];
    

    你可以使用你的配置对象:

    const ip_address = config.ip_address;
    const port = config.port;
    
  • 3

    除了this answer中提到的nconf modulethis answer中提到的node-config之外,还有node-iniparserIniReader,它们似乎更简单.ini配置文件解析器 .

  • 84

    我在这里尝试了一些建议的解决方案,但对它们并不满意,所以我创建了自己的模块 . 它被称为 mikro-config ,主要区别在于它遵循约定优于配置,因此您可以只需要模块并开始使用它 .

    您将配置存储在 /config 文件夹中的普通js或json文件中 . 首先,它加载 default.js 文件,然后加载 /config 目录中的所有其他文件,然后根据 $NODE_ENV 变量加载特定于环境的配置 .

    它还允许使用 local.js 或特定于环境的 /config/env/$NODE_ENV.local.js 覆盖此配置以进行本地开发 .

    你可以在这看看它:

    https://www.npmjs.com/package/mikro-config

    https://github.com/B4nan/mikro-config

  • 0

    很久以后,我找到了一个非常好的Node.js模块来管理配置:nconf .

    一个简单的例子:

    var nconf = require('nconf');
    
    // First consider commandline arguments and environment variables, respectively.
    nconf.argv().env();
    
    // Then load configuration from a designated file.
    nconf.file({ file: 'config.json' });
    
    // Provide default values for settings not provided above.
    nconf.defaults({
        'http': {
            'port': 1337
        }
    });
    
    // Once this is in place, you can just use nconf.get to get your settings.
    // So this would configure `myApp` to listen on port 1337 if the port
    // has not been overridden by any of the three configuration inputs
    // mentioned above.
    myApp.listen(nconf.get('http:port'));
    

    它还支持在Redis中存储设置,编写配置文件,并且具有相当可靠的API,并且作为Flatiron框架计划的一部分,还受到一个备受推崇的Node.js商店Nodejitsu的支持,因此它应该是相当具有前瞻性 .

    看看nconf at Github .

  • 29

    很长一段时间,我过去常常使用解决方案中提到的方法 . 然而,关于明文的秘密安全性存在担忧 . 您可以在 config 之上使用另一个包,以便处理安全位 .

    看看这个:https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/

  • 3

    我将创建一个文件夹作为配置文件命名为 config.js ,稍后我会在需要的地方使用此文件,如下所示

    config.js的示例

    module.exports = {
        proxyURL: 'http://url:port',
        TWITTER: {
            consumerkey: 'yourconsumerkey',
            consumerSecrete: 'yourconsumersecrete'
        },
        GOOGLE: {
            consumerkey: 'yourconsumerkey',
            consumerSecrete: 'yourconsumersecrete'
        },
        FACEBOOK: {
            consumerkey: 'yourconsumerkey',
            consumerSecrete: 'yourconsumersecrete'
        }
    }
    

    然后,如果我想在某处使用此配置文件

    我将首先导入如下

    var config = require('./config');

    我可以访问如下的值

    const oauth = OAuth({
        consumer: {
            key: config.TWITTER.consumerkey,
            secret: config.TWITTER.consumerSecrete
        },
        signature_method: 'HMAC-SHA1',
        hash_function(base_string, key) {
            return crypto.createHmac('sha1', key).update(base_string).digest('base64');
        }
    });
    
  • 6

    只需使用 npm module config (下载量超过300000)

    https://www.npmjs.com/package/config

    Node-config为您的应用部署组织层次结构配置 .

    它允许您定义一组默认参数,并为不同的部署环境(开发,qa,登台, 生产环境 等)扩展它们 .

    $ npm install config
    $ mkdir config
    $ vi config/default.json
    
    
    {
          // Customer module configs
          "Customer": {
            "dbConfig": {
              "host": "localhost",
              "port": 5984,
              "dbName": "customers"
            },
            "credit": {
              "initialLimit": 100,
              // Set low for development
              "initialDays": 1
            }
          }
    }
    
    
    
    $ vi config/production.json
    
    {
      "Customer": {
        "dbConfig": {
          "host": "prod-db-server"
        },
        "credit": {
          "initialDays": 30
        }
      }
    }
    
    
    
    $ vi index.js
    
    var config = require('config');
    //...
    var dbConfig = config.get('Customer.dbConfig');
    db.connect(dbConfig, ...);
    
    if (config.has('optionalFeature.detail')) {
      var detail = config.get('optionalFeature.detail');
      //...
    }
    
    
    $ export NODE_ENV=production
    $ node index.js
    
  • 11

    对于那些正在访问这个旧线程的人来说,这是一个我认为很好的包 .

    https://www.npmjs.org/package/config

  • 1

    Convict是另一个添加模式以进行验证的选项 . 与nconf一样,它支持从环境变量,参数,文件和json对象的任意组合加载设置 .

    自述文件中的示例:

    var convict = require('convict');
    var conf = convict({
      env: {
        doc: "The applicaton environment.",
        format: ["production", "development", "test"],
        default: "development",
        env: "NODE_ENV"
      },
      ip: {
        doc: "The IP address to bind.",
        format: "ipaddress",
        default: "127.0.0.1",
        env: "IP_ADDRESS",
      },
      port: {
        doc: "The port to bind.",
        format: "port",
        default: 0,
        env: "PORT"
      }
    });
    

    入门文章:Taming Configurations with node-convict

  • 189

    您也可以查看node-config,它根据 $HOST$NODE_ENV 变量(有点像RoR)加载配置文件:documentation .

    这对于不同的部署设置( developmenttestproduction )非常有用 .

  • 1

    我为我的软件包使用了 package.json ,为我的配置使用了 config.js ,它看起来像:

    var config = {};
    
    config.twitter = {};
    config.redis = {};
    config.web = {};
    
    config.default_stuff =  ['red','green','blue','apple','yellow','orange','politics'];
    config.twitter.user_name = process.env.TWITTER_USER || 'username';
    config.twitter.password=  process.env.TWITTER_PASSWORD || 'password';
    config.redis.uri = process.env.DUOSTACK_DB_REDIS;
    config.redis.host = 'hostname';
    config.redis.port = 6379;
    config.web.port = process.env.WEB_PORT || 9980;
    
    module.exports = config;
    

    我从我的项目加载配置:

    var config = require('./config');
    

    然后我可以从 config.db_hostconfig.db_port 等访问我的东西...如果我不想在源代码管理中存储密码,我可以使用硬编码参数或存储在环境变量中的参数 .

    我还生成 package.json 并插入依赖项部分:

    "dependencies": {
      "cradle": "0.5.5",
      "jade": "0.10.4",
      "redis": "0.5.11",
      "socket.io": "0.6.16",
      "twitter-node": "0.0.2",
      "express": "2.2.0"
    }
    

    当我将项目克隆到本地计算机时,我运行 npm install 来安装软件包 . 关于here的更多信息 .

    该项目存储在GitHub中,为我的 生产环境 服务器添加了遥控器 .

  • 1

    您也可以查看符合twelve-factor app原则的dotenv .

    我曾经使用node-config,但出于这个原因创建了dotenv . 它是完全受到ruby的dotenv库的启发 .

    用法非常简单:

    var dotenv = require('dotenv');
    dotenv.load();
    

    然后你只需创建一个.env文件并将设置放在那里:

    S3_BUCKET=YOURS3BUCKET
    SECRET_KEY=YOURSECRETKEYGOESHERE
    OTHER_SECRET_STUFF=my_cats_middle_name
    

    这是nodejs的dotenv .

  • 1

    我在游戏中有点晚了,但我找不到我需要的东西 - 或者其他任何地方 - 所以我自己写了一些东西 .

    我对配置机制的要求如下:

    • 支持前端 . 如果前端无法使用配置,有什么意义?

    • 支持 settings-overrides.js - 看起来相同但允许在 settings.js 覆盖配置 . 这里的想法是在不更改代码的情况下轻松修改配置 . 我觉得它对saas很有用 .

    即使我不太关心支持环境 - 这将解释如何将其轻松添加到我的解决方案中

    var publicConfiguration = {
        "title" : "Hello World"
        "demoAuthToken" : undefined, 
        "demoUserId" : undefined, 
        "errorEmail" : null // if null we will not send emails on errors. 
    
    };
    
    var privateConfiguration = {
        "port":9040,
        "adminAuthToken":undefined,
        "adminUserId":undefined
    }
    
    var meConf = null;
    try{
        meConf = require("../conf/dev/meConf");
    }catch( e ) { console.log("meConf does not exist. ignoring.. ")}
    
    
    
    
    var publicConfigurationInitialized = false;
    var privateConfigurationInitialized = false;
    
    function getPublicConfiguration(){
        if (!publicConfigurationInitialized) {
            publicConfigurationInitialized = true;
            if (meConf != null) {
                for (var i in publicConfiguration) {
                    if (meConf.hasOwnProperty(i)) {
                        publicConfiguration[i] = meConf[i];
                    }
                }
            }
        }
        return publicConfiguration;
    }
    
    
    function getPrivateConfiguration(){
        if ( !privateConfigurationInitialized ) {
            privateConfigurationInitialized = true;
    
            var pubConf = getPublicConfiguration();
    
            if ( pubConf != null ){
                for ( var j in pubConf ){
                    privateConfiguration[j] = pubConf[j];
                }
            }
            if ( meConf != null ){
                  for ( var i in meConf ){
                      privateConfiguration[i] = meConf[i];
                  }
            }
        }
        return privateConfiguration;
    
    }
    
    
    exports.sendPublicConfiguration = function( req, res ){
        var name = req.param("name") || "conf";
    
        res.send( "window." + name + " = " + JSON.stringify(getPublicConfiguration()) + ";");
    };
    
    
    var prConf = getPrivateConfiguration();
    if ( prConf != null ){
        for ( var i in prConf ){
            if ( prConf[i] === undefined ){
    
                throw new Error("undefined configuration [" + i + "]");
            }
            exports[i] = prConf[i];
        }
    }
    
    
    return exports;
    

    解释

    • undefined 表示此属性是必需的

    • null 表示它是可选的

    • meConf - 目前代码是 app 下文件的目标 . meConf 是覆盖文件,目标是 conf/dev - 我的vcs会忽略它 .

    • publicConfiguration - 将从前端和后端可见 .

    • privateConfiguration - 仅从后端可见 .

    • sendPublicConfiguration - 将公开公共配置并将其分配给全局变量的路由 . 例如,下面的代码将公共配置公开为前端的全局变量myConf . 默认情况下,它将使用全局变量名 conf .

    app.get(“/ backend / conf”,require(“conf”) . sendPublicConfiguration);

    覆盖的逻辑

    • privateConfiguration与publicConfiguration合并,然后是meConf .

    • publicConfiguration检查每个键是否具有覆盖,并使用该覆盖 . 这样我们就不会露出任何私密的东西 .

    添加环境支持

    即使我没有找到有用的“环境支持”,也许有人会 .

    要添加环境支持,您需要将meConf require语句更改为此类(伪代码)

    if(environment ==“production”){meConf = require(“../ conf / dev / meConf”) . production; }

    if(environment ==“development”){meConf = require(“../ conf / dev / meConf”) . development; }

    同样,您可以为每个环境提供一个文件

    meConf.development.js
     meConf.production.js
    

    并导入正确的 . 其余的逻辑保持不变 .

  • 20

    我的解决方案很简单:

    在./config/index.js中加载环境配置

    var env = process.env.NODE_ENV || 'development'
      , cfg = require('./config.'+env);
    
    module.exports = cfg;
    

    在./config/config.global.js中定义一些默认值

    var config = module.exports = {};
    
    config.env = 'development';
    config.hostname = 'dev.example.com';
    
    //mongo database
    config.mongo = {};
    config.mongo.uri = process.env.MONGO_URI || 'localhost';
    config.mongo.db = 'example_dev';
    

    覆盖./config/config.test.js中的默认值

    var config = require('./config.global');
    
    config.env = 'test';
    config.hostname = 'test.example';
    config.mongo.db = 'example_test';
    
    module.exports = config;
    

    在./models/user.js中使用它:

    var mongoose = require('mongoose')
    , cfg = require('../config')
    , db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
    

    在测试环境中运行您的应用:

    NODE_ENV=test node ./app.js
    

    这在这里有更详细的解释:http://www.chovy.com/node-js/managing-config-variables-inside-a-node-js-application/

相关问题