- 代码库:一份版本控制下的基准代码库,多份部署
应用程序的源代码仓库应该只包含一个应用程序,并列出它所依赖的资源清单。对于不同的环境,我们应该不需要重新编译或打包应用程序。每个环境中特有的设置应该与代码无关
- 依赖:显示声明和隔离依赖关系
应该显式地声明应用程序的依赖关系,并且可以通过依赖项管理软件(如Apache Maven)的仓库,下载任意或所有的依赖关系。
- 配置:在环境中存储配置
应用程序的代码应用配置严格区分开来。程序的配置应用各个环境各自管理。
- 后端服务:把后端服务作为附加资源
后端服务是十二要素程序正常运行所需要依赖的任何服务。举例说明,后端服务包括数据库、API驱动的RESTful Web服务、SMTP服务器或FTP服务器。 后端服务被认为是应用程序的某种资源。这些资源在运行期间被绑定到应用程序上。十二要素程序应该在无须代码改动的前提下,可以从一个测试环境中的嵌入式SQL数据库,切换到预发布环境下的一个独立MySQL数据库。
- 构建、发布、运行:严格分离构建和运行阶段
构建阶段
构建阶段将应用程序的源代码编译或打包到一个程序包中。创建的包被称为一次构建物。
将应用源代码打包。
发布阶段
发布阶段需要将某次构建与其配置相结合。随后,创建出的发布文件应该可以在某个执行环境中运行。无论是使用版本号还是时间戳,每个版本应该有一个唯一的标识符。每个发布文件都应该被添加到一个目录中,可以通过发布管理工具回滚到之前的发布版本。
构建包+环境配置组成一个发布文件。
运行阶段
运行阶段(通常称为运行时)是指在可执行环境中运行一个指定的应用版本。 通过将这些阶段分成独立的流程,在运行时就完全不可能去更改任何程序代码。更改应用程序代码的唯一方法,就是通过构建阶段来创建一个新的版本,或者回滚到之前部署的某个版本。
将发布文件运行。
- 进程:将应用程序作为一个或多个无状态进程执行
无状态进程方便程序扩缩容。
- 端口绑定:通过端口绑定暴露服务
十二要素程序本身是完全独立的,其运行不需要依托于任何的web容器,就可以对外提供web服务能力。每个应用程序通过将自身HTTP端口绑定到执行环境中来对外提供访问能力。
- 并发:通过进程模型扩展
十二要素程序必须能够水平扩展,并且能够将请求分发到负载均衡背后的多个程序实例处理。在保证程序无状态的前提下,我们可以通过增加多个节点来水平扩展程序的处理能力。
除增加进程水平扩展的方式,我们还可以通过增加线程来并行处理任务的方式提升程序的数据处理能力。
- 易处理:通过快速启动和正常关机来最大限度的提高健壮性
应用程序应该是可以快速启停的,快速启动从而不影响程序的整体可用性;在执行的任意时刻可以终止,并且能够优雅的释放线程以适应程序高频次迭代的需求。
- 开发/生产环境一致:尽可能的保持开发、预发布和生产环境的配置一致
应防止不同环境之间存在的差异。每个环境应尽可能使用相同的技术和框架,避免因细小的意外差异导致不一致的行为出现。
- 日志:将日志视为事件流
十二要素程序将写日志看作到标准输出的一个有序的事件流。应用程序不应负责管理自身日志文件的存储。应用程序日志输出的收集和归档工作应该由运行环境来完成。
- 管理进程:将管理任务作为一次性进程运行
有时,应用程序的开发人员需要运行一次性的管理任务。这类任务可能包括数据库迁移或运行已提交到源代码仓库中的一次性脚本。这些都被认为是管理进程。管理进程应该在应用程序的执行环境中运行,并将脚本提交到代码仓库中,以便保持各个环境之间的一致性。
数据库脚本等提交到代码仓库做版本管理。