dotenv 是不是与十二要素应用程序相矛盾?

Posted

技术标签:

【中文标题】dotenv 是不是与十二要素应用程序相矛盾?【英文标题】:Does dotenv contradict the Twelve-Factor App?dotenv 是否与十二要素应用程序相矛盾? 【发布时间】:2017-09-12 16:13:11 【问题描述】:

我已经阅读了有关Twelve Factor App's Config - Section III 的信息,并在 NodeJS 中寻找了一种方法。似乎大多数人推荐dotenv 将配置存储在环境变量中。

但是,dotenv 似乎与十二要素应用程序相矛盾,如下所述:

另一种配置方法是使用未检入修订控制的配置文件,例如 Rails 中的 config/database.yml。与使用检入代码仓库的常量相比,这是一个巨大的改进,但仍然存在弱点:很容易将配置文件错误地检入代码仓库;配置文件倾向于分散在不同的地方和不同的格式,使得在一个地方查看和管理所有配置变得困难。此外,这些格式往往是特定于语言或框架的。

十二因素应用程序将配置存储在环境变量中(通常缩写为 env vars 或 env)。环境变量很容易在部署之间更改,而无需更改任何代码;与配置文件不同,它们被意外签入代码仓库的可能性很小;与自定义配置文件或其他配置机制(如 Java 系统属性)不同,它们是与语言和操作系统无关的标准。

理解这句话,似乎使用 dotenv,您将创建一个配置文件 .env,然后将它们导出为环境变量。

这不会违反十二要素应用程序吗,因为.env 文件可能会被意外签入代码仓库?

【问题讨论】:

技术说明:.env 文件不会以任何方式导出环境变量,有些库只是让您使用.env 文件来扩展process.env,而无需设置虚拟环境或放置不在容器/VM 中工作时,全局环境中仅与此应用相关的值 【参考方案1】:

OP 提出了一个深思熟虑的问题。

我会说 dotenv 与第 3 节的 12 因素相矛盾,原因有两个。

    根据定义,即本段:“配置的另一种方法是使用未签入修订控制的配置文件,......仍然有缺点:很容易错误地将配置文件签入到repo; ...(因此 12 因素应用程序使用不同的方法)将配置存储在环境变量中”,现在你看到了,只是因为 .env 文件可以/应该在 .gitignore 中声明, 并不能使 dotenv 免于“容易错误地将配置文件签入 repo”的审查。

    如果一个应用从 且仅从 env var 读取配置,则该应用可能完全符合 12 因素第 3 节。但是一个 dotenv 功能是允许应用程序自动拾取./.env(如果可用)。从这个意义上说,.env 文件——尽管它具有欺骗性的名称——一个配置文件,彻头彻尾。同样,这属于 12 因素明确避免的配置方法类别。

话虽如此,dotenv 仍然是可行的选择之一。其他选项包括:在 docker 层管理环境变量;或在 unix 用户的 .*rc 文件中;或在网络服务器配置中;或/etc/profile(引自this another SO post)。 dotenv 提供了一种最通用的文件格式(fwiw,docker env_file 也同样简单,尽管它们的规格不同),但是 dotenv 是唯一一种“污染”目标应用程序代码库的解决方案。

底线,dotenv 很好,有趣的是许多dotenv 实现继承了它从 12 因素应用程序原则开始的声明,但只有少数人承认其 .env 方法偏离了 12-因素应用程序。

【讨论】:

【参考方案2】:

在有人实际提交并推送.env 之前,不会违反 12 因素;)

.env 文件也可以存储在 repo 本身之外,因为库或应用程序仍然必须读取 .env 文件并将变量推送到环境中。根据您的实现,这可以像将路径从 ".env" 更改为 "../.env" 一样简单。

使用.env 文件可能是一个很好的折衷方案,可以让开发人员轻松管理环境,但在部署期间仍与更好的环境实践兼容。我可能有 30-40 个 12 因素风格的应用程序在虚拟机中运行,如果没有像 .env 这样的“垫片”,必须单独管理每个环境是令人生畏的。

【讨论】:

【参考方案3】:

大多数版本控制系统都有忽略某些文件的方法。

Git 有 .gitignore

SVN 有"Special Ignores"

附带说明,这些技术同样用于忽略node_modules 目录,以避免不必要地复制文件。

【讨论】:

以上是关于dotenv 是不是与十二要素应用程序相矛盾?的主要内容,如果未能解决你的问题,请参考以下文章

微服务-十二要素

Heroku创始人Adam Wiggins发布十二要素应用宣言

云计算时代应用设计十二要素

云原生必备概念 — CAP 定理十二要素应用

为啥我的交叉验证错误分类错误率与测试数据集成功率相矛盾

Dotenv\Dotenv::__construct() 不是 Dotenv\Loader 的实例