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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5869216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:08:41  来源:igfitidea点击:

How to store Node.js deployment settings/configuration files?

node.jsconfiguration-files

提问by mikl

I have been working on a few Node apps, and I've been looking for a good pattern of storing deployment-related settings. In the Django world (where I come from), the common practise would be to have a settings.pyfile containing the standard settings (timezone, etc), and then a local_settings.pyfor deployment specific settings, ie. what database to talk to, what memcache socket, e-mail address for the admins and so on.

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

I have been looking for similar patterns for Node. Just a config file would be nice, so it does not have to be jammed in with everything else in app.js, but I find it important to have a way to have server-specific configuration in a file that is not in source control. The same app could well be deployed across different servers with wildly different settings, and having to deal with merge conflicts and all that is not my idea of fun.

我一直在为 Node.js 寻找类似的模式。只需一个配置文件就好了,因此它不必与app.js. 相同的应用程序很可能部署在具有截然不同设置的不同服务器上,并且必须处理合并冲突以及所有这些都不是我的乐趣所在。

So is there some kind of framework/tool for this, or does everyone just hack something together themselves?

那么是否有某种框架/工具可以解决这个问题,还是每个人都自己动手做一些事情?

采纳答案by mikl

Much later, I found a pretty good Node.js module for managing configuration: nconf.

很久以后,我发现了一个很好的 Node.js 模块来管理配置:nconf

A simple example:

一个简单的例子:

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'));

It also supports storing settings in Redis, writing configuration files, and has a fairly solid API, and is also backed by one of the more well-respected Node.js shops, Nodejitsu, as part of the Flatironframework initiative, so it should be fairly future-proof.

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

Check out nconf at Github.

在 Github 上查看nconf

回答by noli

I use a package.jsonfor my packages and a config.jsfor my configuration, which looks like:

我使用 apackage.json作为我的包和 aconfig.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;

I load the config from my project:

我从我的项目加载配置:

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

and then I can access my things from config.db_host, config.db_port, etc... This lets me either use hardcoded parameters, or parameters stored in environmental variables if I don't want to store passwords in source control.

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

I also generate a package.jsonand insert a dependencies section:

我还生成了一个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"
}

When I clone the project to my local machine, I run npm installto install the packages. More info on that here.

当我将项目克隆到我的本地机器时,我运行npm install以安装包。更多信息在这里

The project is stored in GitHub, with remotes added for my production server.

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

回答by TinyTimZamboni

You can require JSON files as of Node v0.5.x (referencing this answer)

您可以从 Node v0.5.x 开始要求 JSON 文件(参考此答案

config.json:

配置文件:

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

app.js:

应用程序.js:

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

回答by chovy

My solution is fairly simple:

我的解决方案相当简单:

Load the environment config in ./config/index.js

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

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

module.exports = cfg;

Define some defaults in ./config/config.global.js

在 ./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';

Override the defaults in ./config/config.test.js

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

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

config.env = 'test';
config.hostname = 'test.example';
config.mongo.db = 'example_test';

module.exports = config;

Using it in ./models/user.js:

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

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

Running your app in test environment:

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

NODE_ENV=test node ./app.js

回答by scottmotte

You might also look to dotenvwhich follows the tenets of a twelve-factor app.

您还可以查看dotenv,它遵循十二要素 app的原则。

I used to use node-config, but created dotenv for that reason. It was completely inspired by ruby's dotenv library.

我曾经使用 node-config,但因此创建了 dotenv。它完全受到 ruby​​ 的 dotenv 库的启发。

Usage is quite easy:

使用非常简单:

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

Then you just create a .env file and put your settings in there like so:

然后您只需创建一个 .env 文件并将您的设置放入其中,如下所示:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

That's dotenvfor nodejs.

那是nodejs的 dotenv。

回答by lxx

Are you guys using npm to start your scripts (env etc) ?

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

If you use .envfiles you can include them in your package.jsonand use npm to source/start them.

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

Example:

例子:

{
  "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": "*"
  }
}

then run the npm scripts:

然后运行 ​​npm 脚本:

$ npm start-dev

Its described here https://gist.github.com/ericelliott/4152984All credit to Eric Elliot

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

回答by ngryman

You might also look to node-configwhich loads configuration file depending on $HOSTand $NODE_ENVvariable (a little bit like RoR) : documentation.

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

This can be quite useful for different deployment settings (development, testor production).

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

回答by Vanuan

Just do a simple settings.jswith exports:

只需做一个简单settings.jsexports

exports.my_password = 'value'

Then, in your script, do a require:

然后,在您的脚本中,执行以下操作require

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

All your settings now will be availabe via settingsvariable:

您现在所有的设置都可以通过settings变量获得:

settings.my_password // 'value'

回答by B T

I'm going to throw my hat into the ring here because none of these answers address all the critical components that pretty much any system needs. Considerations:

我将在这里大放异彩,因为这些答案都没有解决几乎任何系统都需要的所有关键组件。注意事项:

  • Public configuration (that can be seen by the frontend) vs private configuration (guy mograbi got this one right). And ensuring these are kept separate.
  • Secrets like keys
  • Defaults vs environment-specific overrides
  • Frontend bundles
  • 公共配置(前端可以看到)与私有配置(家伙 mograbi 做对了这一点)。并确保这些是分开的。
  • 像钥匙一样的秘密
  • 默认值与特定于环境的覆盖
  • 前端包

Here's how I do my configuration:

这是我如何进行配置:

  • config.default.private.js- In version control, these are default configuration options that can only be seen by your backend.
  • config.default.public.js- In version control, these are default configuration options that can be seen by backend andfrontend
  • config.dev.private.js- If you need different private defaults for dev.
  • config.dev.public.js- If you need different public defaults for dev.
  • config.private.js- Not in version control, these are environment specific options that override config.default.private.js
  • config.public.js- Not in version control, these are environment specific options that override config.default.public.js
  • keys/- A folder where each file stores a different secret of some kind. This is also not under version control (keys should never be under version control).
  • config.default.private.js- 在版本控制中,这些是默认配置选项,只能由您的后端看到。
  • config.default.public.js- 在版本控制中,这些是后端前端可以看到的默认配置选项
  • config.dev.private.js- 如果您需要不同的开发私有默认值。
  • config.dev.public.js- 如果您需要不同的开发公共默认值。
  • config.private.js- 不在版本控制中,这些是覆盖的环境特定选项 config.default.private.js
  • config.public.js- 不在版本控制中,这些是覆盖的环境特定选项 config.default.public.js
  • keys/- 每个文件存储某种不同秘密的文件夹。这也不受版本控制(密钥不应该受版本控制)。

I use plain-old javascript files for configuration so I have the full power of the javascript langauge (including comments and the ability to do things like load the default config file in the environment-specific file so they can then be overridden). If you want to use environment variables, you can load them inside those config files (tho I recommend against using env vars for the same reason I don't recommend using json files - you don't have the power of a programming language to construct your config).

我使用普通的 javascript 文件进行配置,因此我拥有 javascript 语言的全部功能(包括注释和执行诸如在特定于环境的文件中加载默认配置文件以便随后可以覆盖它们)的能力。如果你想使用环境变量,你可以将它们加载到这些配置文件中(我建议不要使用环境变量,原因与我不建议使用 json 文件的原因相同——你没有编程语言的能力来构建你的配置)。

The reason each key is in a separate file is for installer use. This allows you to have an installer that creates keys on-machine and stores them in the keys folder. Without this, your installer might fail when you load your configuration file that can't access your keys. This way you can traverse the directory and load any key files that are in that folder without having to worry about what exists and what doesn't in any given version of your code.

每个密钥位于单独文件中的原因是供安装程序使用。这允许您拥有一个在机器上创建密钥并将它们存储在密钥文件夹中的安装程序。如果没有这个,当您加载无法访问您的密钥的配置文件时,您的安装程序可能会失败。通过这种方式,您可以遍历目录并加载该文件夹中的任何关键文件,而不必担心任何给定版本的代码中存在哪些内容,哪些不存在。

Since you probably have keys loaded in your private configuration, you definitelydon't want to load your private config in any frontend code. While its probably strictly more ideal to completely separate your frontend codebase from your backend, a lot of times that PITA is a big enough barrier to prevent people from doing it, thus private vs public config. But there's two things I do to prevent private config being loaded in the frontend:

由于您可能在私有配置中加载了密钥,因此您绝对不想在任何前端代码中加载私有配置。虽然将前端代码库与后端完全分开可能更理想,但很多时候 PITA 是一个足够大的障碍来阻止人们这样做,因此私有配置与公共配置。但是我做了两件事来防止在前端加载私有配置:

  1. I have a unit test that ensures my frontend bundles don't contain one of the secret keys I have in the private config.
  2. I have my frontend code in a different folder than my backend code, and I have two different files named "config.js" - one for each end. For backend, config.js loads the private config, for frontend, it loads the public config. Then you always just require('config') and don't worry about where it comes from.
  1. 我有一个单元测试,可确保我的前端包不包含我在私有配置中拥有的密钥之一。
  2. 我的前端代码与后端代码位于不同的文件夹中,并且我有两个名为“config.js”的不同文件 - 每一端一个。对于后端,config.js 加载私有配置,对于前端,它加载公共配置。然后你总是只需要('config')而不用担心它来自哪里。

One last thing: your configuration should be loaded into the browser via a completelyseparate file than any of your other frontend code. If you bundle your frontend code, the public configuration should be built as a completely separate bundle. Otherwise, your config isn't really config anymore - its just part of your code. Config needs to be able to be different on different machines.

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

回答by hurrymaplelad

Convictis another option that adds a schema for validation. Like nconf, it supports loading settings from any combination of environment variables, arguments, files, and json objects.

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

Example from the README:

README 中的示例:

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"
  }
});

Getting started article: Taming Configurations with node-convict

入门文章: 使用 node-convict 驯服配置