--- title: 'Express 教程 7: 部署到生产环境' slug: learn/Server-side/Express_Nodejs/deployment tags: - Express - Learn - Node - 初学者 - 部署 translation_of: Learn/Server-side/Express_Nodejs/deployment ---
现在你已经创建(并测试)了一个不错的 本地图书馆 网站了,你打算把它发布到一个公共网络服务器,这样图书馆职工和网络上的其他成员就可以访问它了。这篇文章总结了你可以怎样找到一台主机部署你的网站,以及你需要为站点准备到生产环境做什么。
预备知识: | 完成前面所有的指南主题,包括 Express Tutorial Part 6: Working with forms. |
---|---|
目标: | 学习你可以怎样以及在哪里部署一个Express 应用到生产环境。 |
一旦您的站点完成(或完成“足够”以开始公共测试),您将需要将其托管在比您的个人开发计算机,更公开和可访问的地方。
到目前为止,您一直在开发环境中工作,使用 Express / Node 作为Web服务器,将您的站点共享到本地浏览器/网络,并使用(不安全的)开发设置运行您的网站,以显示调试和其他私人信息。在您可以在外部托管网站之前,您首先必须:
本教程提供了,有关选择托管站点的选项的一些指导,简要概述了为使您的Express 应用程序准备好生产,所需执行的操作,以及如何将LocalLibrary 网站安装到 Heroku云托管上的工作示例服务。
请记住,您不必使用Heroku - 还有其他托管服务可用。我们还提供了一个单独的教程,以展示如何在 PWS/Cloud Foundry 上安装LocalLibrary。
生产环境是服务器计算机提供的环境,您可以在其中运行网站,以供外部使用。环境包括:
服务器计算机,可以位于您的场所,并通过快速链接,连接到 Internet,但使用 “托管在云上” 的计算机更为常见。这实际上意味着,您的代码运行在托管公司的数据中心的某台远程计算机(或可能是“虚拟”计算机)。远程服务器,通常会以特定价格提供互联网连接,和一些保证级别的计算资源(例如CPU,RAM,存储器等)。
这种可远程访问的计算/网络硬件,称为基础架构即服务(IaaS)。许多IaaS 供应商,提供预安装特定操作系统的选项,您必须在其上,安装生产环境的其他组件。其他供应商,允许您选择功能更全面的环境,可能包括完整的 node 设置。
注意: 预构建环境,可以使您的网站设置变得非常简单,因为它们会减少配置,但可用选项可能会限制您使用不熟悉的服务器(或其他组件),并且可能基于较旧版本的操作系统。通常最好自己安装组件,以便获得所需的组件,并且当您需要升级系统的某些部分时,您可以知道从哪里开始!
其他托管服务提供商,支持 Express 作为平台即服务(PaaS)产品的一部分。使用此类托管时,您无需担心大多数生产环境(服务器,负载平衡器等),因为主机平台会为您处理这些问题。这使得部署非常简单,因为您只需要专注于 Web 应用程序,而不是任何其他服务器基础结构。
一些开发人员选择 IaaS ,相对于 PaaS ,IaaS 提供更高灵活性,而其他开发人员偏好 PaaS 的降低维护开销,和更轻松的扩展性。当您在一开始使用时,在 PaaS 系统上设置您的网站,要容易得多,因此我们将在本教程中使用 PaaS。
提示: 如果您选择Node/Express友好的托管服务提供商,他们应该提供,有关如何使用Web服务器,应用程序服务器,反向代理等不同配置,来设置 Express 网站的说明。例如,在数字海洋node社区文档中,有许多各种配置的手把手指南。
众所周知,众多托管服务提供商,都积极支持或与Node(和Express)合作。这些供应商提供不同类型的环境(IaaS,PaaS),以及不同价格的不同级别的计算和网络资源。
提示: 有很多托管解决方案,他们的服务和定价,可能会随着时间而改变。虽然我们在下面介绍几个选项,但在选择托管服务提供商之前,有必要自己进行互联网搜索。
选择主机时需要考虑的一些事项:
当你刚开始时,好消息是有很多网站提供“免费”的计算环境,尽管有一些条件。例如, Heroku “永远” 提供免费但资源有限的PaaS 环境,而 Amazon Web Services, Microsoft Azure 和开源选项 PWS/Cloud Foundry 在您第一次加入时,提供免费信用额度。
许多提供商还拥有“基本”层,可提供更多有用的计算能力,和更少的限制。举例来说, Digital Ocean 是一个流行的托管服务提供商,它提供了一个相对便宜的基本计算层(在本教程写作时,是每月5美元的较低范围)。
注意: 请记住,价格不是唯一的选择标准。如果您的网站成功,可能会发现可扩展性是最重要的考虑因素。
发布网站时,要考虑的主要问题是网络安全性和性能。至少,您需要删除开发期间,错误页面上包含的堆栈跟踪,整理日志记录,并设置适当的标头,以避免许多常见的安全威胁。
在以下小节中,我们概述了您应该对应用进行的、最重要的更改。
提示: Express文档中还有其他有用的提示 - 请参阅“生产最佳实践:性能和可靠性”,以及“生产最佳实践:安全性”。
我们可以通过将 NODE_ENV
环境变量,设置为 production ,来删除错误页面中的堆栈跟踪(默认设置为 “development” )。除了生成较为不详细的错误消息之外,还要将变量设置为生产缓存视图模板,和从CSS扩展生成的CSS文件。测试表明,将NODE_ENV
设置为生产,可以将应用程序性能提高三倍!
可以使用导出或环境文件,或使用OS初始化系统,以进行此更改。
注意: 这实际上是在环境设置,而不是应用中所做的更改,但重要的是,要注意这里!我们将在下面,展示如何为我们的托管示例设置。
记录呼叫会对高流量网站产生影响。在生产环境中,您可能需要记录网站活动(例如,跟踪流量,或记录API调用),但您应尝试最小化为调试目的而添加的日志记录量。
在生产环境中,最小化“调试”日志记录的一种方法,是使用类似调试debug 的模块,允许您通过设置环境变量,来控制执行的日志记录。例如,下面的代码片段,显示了如何设置“author”日志记录。调试变量使用名称“author”声明,并且将自动显示,来自此对象的所有日志的前缀“author”。
var debug = require('debug')('author'); // Display Author update form on GET exports.author_update_get = function(req, res, next) { req.sanitize('id').escape().trim(); Author.findById(req.params.id, function(err, author) { if (err) { debug('update error:' + err); return next(err); } //On success res.render('author_form', { title: 'Update Author', author: author }); }); };
然后,您可以通过在DEBUG
环境变量中,将它们指定为逗号分隔列表,来启用特定日志集。您可以设置显示作者和书籍日志的变量,如图所示(也支持通配符)。
#Windows set DEBUG=author,book #Linux export DEBUG="author,book"
挑战: 调用debug
可以替换您以前使用console.log()
或console.error()
执行的日志记录。通过调试模块debug进行日志记录,替换代码中的所有console.log()
调用。通过设置 DEBUG 变量,并在其中记录对日志记录的影响,在开发环境中,打开和关闭日志记录。
如果您需要记录网站活动,可以使用 Winston 或 Bunyan 等日志库。有关此主题的更多信息,请参阅:生产最佳实践:性能和可靠性。
Web服务器,通常可以压缩发送回客户端的 HTTP 响应,从而显着减少客户端获取和加载页面所需的时间。使用的压缩方法,取决于客户端在请求中支持的解压缩方法(如果不支持压缩方法,则响应将以未压缩的方式发送)。
您可以使用压缩中间件 compression,将其添加到您的站点。通过在项目的根目录下,运行以下命令,将其安装到项目中。
npm install compression
打开./app.js,并导入压缩库,如图所示。使用use()
方法,将压缩库添加到中间件链(这应该出现在您想要压缩的任何路由之前 - 在本教程这种情况下,全部都是!)
var catalogRouter = require('./routes/catalog'); //Import routes for "catalog" area of site var compression = require('compression'); // Create the Express application object var app = express(); ... app.use(compression()); //Compress all routes app.use(express.static(path.join(__dirname, 'public'))); app.use('/', indexRouter); app.use('/users', usersRouter); app.use('/catalog', catalogRouter); // Add catalog routes to middleware chain. ...
注意: 对于生产中流量较大的网站,您不会使用此中间件。相反,你会使用像 Nginx 这样的反向代理。
Helmet 是一个中间件包,可以通过设置适当的 HTTP 标头,来帮助保护您的应用,免受一些众所周知的 Web 漏洞的影响(有关它设置的标头/防护漏洞的详细信息,请参阅文档)。
通过在项目的根目录下,运行以下命令,将其安装到项目中。
npm install helmet
打开./app.js,并导入如图所示的 helmet 库。然后使用use()
方法将模块添加到中间件链。
var compression = require('compression'); var helmet = require('helmet'); // Create the Express application object var app = express(); app.use(helmet()); ...
注意: 上面的命令,添加了对大多数站点有意义的可用标头子集。您可以按照npm上的说明,根据需要添加/禁用特定标头。
本节提供了如何在Heroku PaaS cloud云上安装LocalLibrary的实际演示。
Heroku 是运行时间最长,且最受欢迎的基于云的 PaaS 服务之一。它最初只支持 Ruby 应用程序,但现在可用于托管来自许多编程环境的应用程序,包括Node(以及Express)!
我们选择使用 Heroku 有以下几个原因:
虽然 Heroku 非常适合举办此演示,但它可能并不适合您的真实网站。 Heroku可以轻松设置和扩展,但代价是灵活性较低,而且一旦退出免费套餐,可能会花费更多。
Heroku在一个或多个“Dynos”中运行网站,这些“Dynos”是独立的虚拟化Unix容器,提供运行应用程序所需的环境。 Dynos 是完全隔离的,并且有一个短暂的文件系统(一个短暂的文件系统,每次dyno重新启动时都会清理/清空)。 dynos 默认共享的唯一内容,是应用程序配置变量。 Heroku内部使用负载均衡器,将Web流量分配给所有“web”dynos。由于它们之间没有任何共享,Heroku可以通过添加更多dynos,来水平扩展应用程序(当然,您可能还需要扩展数据库,以接受其他连接)。
由于文件系统是短暂的,因此无法直接安装应用程序所需的服务(例如数据库,队列,缓存系统,存储,电子邮件服务等)。相反,Heroku Web应用程序使用 Heroku 或第三方作为独立“附加组件”提供的支持服务。连接到Web应用程序后,可以通过环境变量,在Web应用程序中访问附加服务。
为了执行您的应用程序,Heroku需要能够设置适当的环境和依赖关系,并了解它是如何启动的。对于Node应用程序,它所需的所有信息都是从package.json文件中获取的。
开发人员使用特殊的客户端应用程序/终端,与Heroku交互,这很像Unix bash脚本。这允许您上传存储在git存储库中的代码,检查正在运行的进程,查看日志,设置配置变量等等!
为了让我们的应用程序在Heroku上工作,我们需要将我们的Express Web应用程序放入git存储库,并对 package.json 进行一些小的更改。完成后,我们可以设置Heroku帐户,获取Heroku客户端,并使用它来安装我们的网站。
这是您开始教程所需的全部概述(有关更全面的指南,请参阅带有Node.js的Heroku入门)。
Heroku 与 git 源代码版本控制系统紧密集成,使用它来上传/同步您对实时运行系统所做的任何更改。它通过添加一个名为 heroku 的新 Heroku“远程”存储库,来指向您在Heroku云上的源存储库。在开发期间,您使用 git 在“主”存储库 master 中存储更改。如果要部署站点,请将更改同步到 Heroku 存储库。
注意: 如果您习惯于遵循良好的软件开发实践,那么您可能已经在使用git或其他一些SCM系统。如果您已有git存储库,则可以跳过此步骤。
有很多方法可以使用git,但最简单的方法之一,是首先在GitHub上建立一个帐户,在那里创建存储库,然后在本地同步它:
现在创建了存储库(“repo”),我们将要在本地计算机上克隆它:
git clone https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git这将在当前时间点之后,创建存储库。
cd express-locallibrary-tutorial
最后一步,是复制你的应用程序,然后使用 git ,将文件添加到你的仓库:
add
命令,将所有文件添加到 git。git add -A
> git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: ...
git commit -m "First version of application moved into github"
git push origin master
完成此操作后,您应该可以返回创建存储库的Github上的页面,刷新页面,并查看您的整个应用程序现已上传。使用此添加/提交/推送循环,您可以在文件更改时,继续更新存储库。
提示: 这是备份你的“vanilla”项目的好时机 - 虽然我们将在以下部分中进行的一些更改,可能对任何平台(或开发)上的部署有用,而一些其他的更改可能没有用。
执行此操作的最佳方法,是使用git来管理您的修订。使用git,您不仅可以回到特定的旧版本,而且可以在生产变更的单独“分支”中进行维护,并选择在生产和开发分支之间移动的任何更改。学习Git非常值得,但超出了本主题的范围。
最简单的方法,是将文件复制到另一个位置。使用最符合您对 git 了解的方法!
本节介绍了您需要对 LocalLibrary 应用程序进行的更改,以使其在Heroku上运行。
package.json包含解决应用程序依赖项所需的所有内容,以及启动站点时,应启动的文件。 Heroku检测到此文件的存在,并将使用它来配置您的应用程序环境。
我们当前的package.json中,缺少的唯一有用信息,是 node 的版本。我们可以通过输入命令,找到我们用于开发的 node 版本:
>node --version v8.9.1
打开package.json,并将此信息添加为engines > node 部分,如图所示(使用系统的版本号)。
{ "name": "express-locallibrary-tutorial", "version": "0.0.0", "engines": { "node": "8.9.1" }, "private": true, ...
到目前为止,在本教程中,我们使用了一个硬编码到app.js的单个数据库。通常我们希望,能够为生产和开发创建不同的数据库,接下来我们将修改 LocalLibrary 网站,以从OS环境获取数据库URI(如果已定义),否则使用我们的开发数据库。
打开app.js,并找到设置mongoDB连接变量的行。它看起来像这样:
var mongoDB = 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';
使用以下代码替换该行,该代码使用process.env.MONGODB_URI
从名为MONGODB_URI
的环境变量中,获取连接字符串(如果已设置)(使用您自己的数据库URL,而不是下面的占位符。)
var mongoDB = process.env.MONGODB_URI || 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';
在我们继续之前,让我们再次测试该网站,并确保它不受我们的任何更改的影响。
首先,我们需要获取我们的依赖项(你会记得,我们没有将 node_modules文件夹,复制到我们的 git 树中)。您可以通过在项目根目录的终端中,运行以下命令来执行此操作:
npm install
现在运行该站点(请参阅测试路由的相关命令),并检查该站点,是否仍按预期运行。
接下来,让我们将所有更改保存到 Github。在终端中(在我们的存储库中),输入以下命令:
git add -A git commit -m "Added files and changes required for deployment to heroku" git push origin master
我们现在应该准备开始在 Heroku 上,部署 LocalLibrary。
要开始使用Heroku,您首先需要创建一个帐户(如果您已经拥有一个帐户,并安装了Heroku客户端,请跳过创建并上传网站):
按照 Heroku上的说明,下载并安装Heroku客户端。
安装客户端后,您将能够运行命令。例如,要获得客户端的帮助说明:
heroku help
要创建应用程序,我们在存储库的根目录中,运行“create”命令。这将在我们的本地git环境中,创建一个名为 heroku 的 git remote(“指向远程存储库的指针”)。
heroku create
注意: 如果您愿意,可以在“创建”create 之后指定远程存储库的命名。如果你不这样做,你会得到一个随机的名字。该名称用于默认URL。
然后,我们可以将我们的应用程序,推送到Heroku存储库,如下所示。这将上传应用程序,获取所有依赖项,将其打包到dyno中,然后启动该站点。
git push heroku master
如果我们很幸运,该应用程序现在正在网站上“运行”。要打开浏览器并运行新网站,请使用以下命令:
heroku open
注意: 该站点将使用我们的开发数据库运行。创建一些书本和其他对象,并检查该网站是否按预期运行。在下一节中,我们将其设置为使用我们的新数据库。
您将从前一节回忆起,我们需要将NODE_ENV设置为'production',以便提高性能,并生成更简洁的错误消息。我们通过输入以下命令,来完成此操作:
>heroku config:set NODE_ENV='production' Setting NODE_ENV and restarting limitless-tor-18923... done, v13 NODE_ENV: production
我们还应该使用单独的数据库进行生产,在MONGODB_URI环境变量中,设置其URI。您可以完全按照我们原来的方式,设置新数据库和数据库用户,并获取其URI。您可以如下图所示设置URI(显然,要使用您自己的URI!)
>heroku config:set MONGODB_URI='mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production' Setting MONGODB_URI and restarting limitless-tor-18923... done, v13 MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production
您可以使用heroku config
命令,随时检查配置变量 - 立即尝试:
>heroku config === limitless-tor-18923 Config Vars MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production NODE_ENV: production
Heroku会在更新变量时,重新启动应用程序。如果您现在检查主页,它应该显示对象计数的零值,因为上面的更改,意味着我们现在正在使用新的(空)数据库。
Heroku 使用独立的附加组件,为应用程序提供支持服务 - 例如电子邮件或数据库服务。我们不在本网站中使用任何插件,但它们是使用Heroku的重要部分,因此您可能需要查看主题管理插件(Heroku docs)。
Heroku客户端提供了一些调试工具:
heroku logs # Show current logs heroku logs --tail # Show current logs and keep updating with any new results heroku ps #Display dyno status
本教程介绍在生产环境中,如何配置Express 应用。是Express系列教程的最后一个。我们希望你觉得这些教程有用。你可以在Github上取得完整的源码。
{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}