將 Node.js Express 應用程式部署至 Elastic Beanstalk - AWS Elastic Beanstalk

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

將 Node.js Express 應用程式部署至 Elastic Beanstalk

本節將逐步引導您使用 Elastic Beanstalk 命令列介面 (EB CLI) 將範例應用程式部署至 Elastic Beanstalk,然後更新應用程式以使用 Express 架構。

必要條件

本教學課程需要下列先決條件:

  • Node.js 執行階段

  • 預設的 Node.js 套件管理工具軟體 npm

  • Express 命令列產生器

  • Elastic Beanstalk 命令列介面 (EBCLI)

有關安裝所列出之前三個元件和設定本機開發環境的詳細資訊,請參閱 為 Elastic Beanstalk 設置 Node.js 開發環境。在本教學課程中,您不需要安裝 AWS SDK for Node.js,這也在參考主題中提及。

如需安裝和設定 EB 的詳細資訊CLI,請參閱 安裝 Elastic Beanstalk 指令列介面設定 EB CLI

建立 Elastic Beanstalk 環境

應用程式目錄

對於應用程式原始碼套件,本教學課程使用的是名為 nodejs-example-express-rds 的目錄。為本教學課程建立 nodejs-example-express-rds 目錄。

~$ mkdir nodejs-example-express-rds
注意

本章中的每個教學課程皆會使用其自身的應用程式原始碼套件目錄。目錄名稱與教學課程所使用的範例應用程式名稱相符。

將您目前的工作目錄變更為 nodejs-example-express-rds

~$ cd nodejs-example-express-rds

現在,來設定執行 Node.js 平台和範例應用程式的 Elastic Beanstalk 環境。我們將使用 Elastic Beanstalk 命令列介面 (EB CLI)。

為您的應用程式設定 EB CLI儲存庫,並建立執行 Node.js 平台的 Elastic Beanstalk 環境
  1. 使用 eb init 命令建立一個儲存庫。

    ~/nodejs-example-express-rds$ eb init --platform node.js --region <region>

    此命令會在名為 .elasticbeanstalk 的資料夾內建立組態檔案,其中會指定應用程式使用的環境設定,並以目前資料夾為名建立 Elastic Beanstalk 應用程式。

  2. 使用 eb create 命令建立執行範例應用程式的環境。

    ~/nodejs-example-express-rds$ eb create --sample nodejs-example-express-rds

    本命令會使用 Node.js 平台的預設設定和下列資源,建立負載平衡的環境:

    • EC2 執行個體 – Amazon Elastic Compute Cloud (AmazonEC2) 虛擬機器,設定為在您選擇的平台上執行 Web 應用程式。

      每個平台會執行特定的一套軟體、設定檔和指令碼,來支援特定的語言版本、架構、Web 容器或其組合。大多數平台會使用 Apache 或 NGINX 作為反向代理,該代理位於 Web 應用程式前面,將請求轉送給它,提供靜態資產,並產生存取和錯誤日誌。

    • 執行個體安全群組 – Amazon EC2安全群組,設定為允許連接埠 80 上的傳入流量。此資源可讓來自負載平衡器的HTTP流量到達執行 Web 應用程式的EC2執行個體。在預設情況下,不允許傳輸資料從其他通訊埠傳送。

    • 負載平衡器 - Elastic Load Balancing 負載平衡器,可設定將請求分配到執行您應用程式的執行個體。負載平衡器也讓您的執行個體不需直接連接到網際網路。

    • 負載平衡器安全群組 – Amazon EC2安全群組,設定為允許連接埠 80 上的傳入流量。此資源可讓來自網際網路的HTTP流量達到負載平衡器。在預設情況下,不允許傳輸資料從其他通訊埠傳送。

    • Auto Scaling 群組 - Auto Scaling 群組,設為在執行個體終止或無法使用時,取代該執行個體。

    • Amazon S3 儲存貯體 - 儲存位置,用來儲存當您使用 Elastic Beanstalk 時所建立的原始程式碼、日誌和其他成品。

    • Amazon CloudWatch 警示 – 兩個 CloudWatch 警示,可監控您環境中執行個體的負載,並在負載過高或過低時觸發。當警示觸發時,您的 Auto Scaling 群組會擴展或縮減以進行回應。

    • AWS CloudFormation 堆疊 – Elastic Beanstalk 使用 AWS CloudFormation 啟動環境中的資源並傳播組態變更。資源定義於範本中,您可在 AWS CloudFormation 主控台中檢視此範本。

    • 網域名稱 – 以 形式路由至 Web 應用程式的網域名稱 subdomain.region.elasticbeanstalk.com

      網域安全

      為了增強 Elastic Beanstalk 應用程式的安全性,在公有字尾清單中註冊 elasticbeanstalk.com 網域 ()。 PSL

      如果您需要在 Elastic Beanstalk 應用程式的預設網域名稱中設定敏感 Cookie,我們建議您使用具有__Host-字首的 Cookie 來提高安全性。此做法會保護您的網域,防止跨網站請求偽造嘗試 (CSRF)。如需更多資訊,請參閱 Mozilla 開發人員網路中的設定 Cookie 頁面。

  3. 環境建立完成時,請使用 eb open命令在預設瀏覽器URL中開啟環境的 。

    ~/nodejs-example-express-rds$ eb open

您現在已使用範例應用程式建立 Node.js Elastic Beanstalk 環境。您可以使用自己的應用程式對其進行更新。接下來,我們會更新範例應用程式,以使用 Express 架構。

更新應用程式以使用 Express

使用範例應用程式建立環境後,您可使用自己的應用程式對其進行更新。在此程序中,我們先執行 expressnpm install 命令,以便在應用程式目錄中設定 Express 架構。然後,我們使用 EB CLI以更新的應用程式更新您的 Elastic Beanstalk 環境。

欲更新您的應用程式以使用 Express
  1. 執行 express 命令。這會產生 package.jsonapp.js 以及幾個目錄。

    ~/nodejs-example-express-rds$ express

    當提示您是否要繼續時,請輸入 y

    注意

    如果 express 命令無法使用,您可能未依先前先決條件章節中的所述內容安裝 Express 命令列產生器。或者,您可能需要設定本機電腦的目錄路徑設定,才可執行 express 命令。如需有關設定開發環境的詳細步驟,請參閱先決條件章節,以繼續進行本教學課程。

  2. 設定本機依存項目。

    ~/nodejs-example-express-rds$ npm install
  3. (選用) 確認 Web 應用程式伺服器已啟動。

    ~/nodejs-example-express-rds$ npm start

    您應該會看到類似下列的輸出:

    > nodejs@0.0.0 start /home/local/user/node-express > node ./bin/www

    依預設,伺服器將會在連接埠 3000 上執行。若要測試它,curl http://localhost:3000請在另一個終端機中執行,或在本機電腦上開啟瀏覽器,然後輸入URL地址 http://localhost:3000

    Ctrl+C 來停止伺服器。

  4. 使用 eb deploy 命令將變更部署至您的 Elastic Beanstalk 環境。

    ~/nodejs-example-express-rds$ eb deploy
  5. 一旦環境為綠色並準備就緒,請重新整理 URL以驗證其是否正常運作。您應看到顯示 Welcome to Express 的網頁。

接著,我們會更新 Express 應用程式以提供靜態檔案,並新增新的頁面。

欲設定靜態檔案並新增新的頁面至您的 Express 應用程式
  1. 使用下列內容,在 .ebextensions 資料夾中新增第二個組態檔案:

    nodejs-example-express-rds/.ebextensions/staticfiles.config

    option_settings: aws:elasticbeanstalk:environment:proxy:staticfiles: /stylesheets: public/stylesheets

    此設定會將代理伺服器設定為在應用程式 public 路徑的 /public 資料夾內提供檔案。從代理伺服器靜態提供檔案,能夠減少應用程式負載。如需詳細資訊,請參閱本章先前所述的靜態檔案

  2. (選用) 若要確認靜態映射的設定是否正確,請在 nodejs-example-express-rds/app.js 中註解靜態映射設定。這會從節點應用程式中移除映射。

    // app.use(express.static(path.join(__dirname, 'public')));

    即使在註解此行後,上一個步驟 staticfiles.config 檔案中的靜態檔案映射應仍可成功載入樣式表。若要確認靜態檔案映射是透過代理靜態檔案組態 (而非 Express 應用程式) 載入,請移除 option_settings: 後的值。將其從靜態檔案組態和節點應用程式移除之後,樣式表將無法載入。

    完成測試時,請記得重設 nodejs-example-express-rds/app.jsstaticfiles.config 的內容。

  3. 新增 nodejs-example-express-rds/routes/hike.js。輸入下列內容:

    exports.index = function(req, res) { res.render('hike', {title: 'My Hiking Log'}); }; exports.add_hike = function(req, res) { };
  4. 更新 nodejs-example-express-rds/app.js 以納入三個新的行。

    首先,新增下列行來為此路由添加 require

    var hike = require('./routes/hike');

    您的檔案看起來如下列程式碼片段:

    var express = require('express'); var path = require('path'); var hike = require('./routes/hike');

    然後,請在 nodejs-example-express-rds/app.js 後將下列兩行新增至 var app = express();

    app.get('/hikes', hike.index); app.post('/add_hike', hike.add_hike);

    您的檔案看起來如下列程式碼片段:

    var app = express(); app.get('/hikes', hike.index); app.post('/add_hike', hike.add_hike);
  5. nodejs-example-express-rds/views/index.jade 複製至 nodejs-example-express-rds/views/hike.jade

    ~/nodejs-example-express-rds$ cp views/index.jade views/hike.jade
  6. 使用 eb deploy 命令部署變更。

    ~/nodejs-example-express-rds$ eb deploy
  7. 您的環境將在幾分鐘後更新。環境為綠色並準備就緒後,請重新整理瀏覽器並在 hikes 結尾附加 URL(例如 http://node-express-env-syypntcz2q.elasticbeanstalk.com/hikes),以驗證其是否正常運作。

    您應看到標題為 My Hiking Log (My Hiking Log) 的網頁。

現在,您已建立使用 Express 架構的 Web 應用程式。在下一節中,我們將修改應用程式,以使用 Amazon Relational Database Service (RDS) 來存放健行日誌。

更新應用程式以使用 Amazon RDS

在此後續步驟中,我們會更新應用程式以使用 Amazon RDS for My SQL。

更新您的應用程式以RDS用於 MySQL
  1. 若要建立與 Elastic Beanstalk 環境耦合的 RDS for MySQL 資料庫,請遵循本章稍後包含的新增資料庫主題中的指示。新增資料庫執行個體約需要 10 分鐘。

  2. 使用下列內容更新 package.json 中的相依性區段:

    "dependencies": { "async": "^3.2.4", "express": "4.18.2", "jade": "1.11.0", "mysql": "2.18.1", "node-uuid": "^1.4.8", "body-parser": "^1.20.1", "method-override": "^3.0.0", "morgan": "^1.10.0", "errorhandler": "^1.5.1" }
  3. 執行 npm install

    ~/nodejs-example-express-rds$ npm install
  4. 更新 app.js,以便連接至資料庫、建立資料表,並插入單一預設增長日誌。每次部署此應用程式時,其會捨棄先前的增長資料表,並重新建立。

    /** * Module dependencies. */ const express = require('express') , routes = require('./routes') , hike = require('./routes/hike') , http = require('http') , path = require('path') , mysql = require('mysql') , async = require('async') , bodyParser = require('body-parser') , methodOverride = require('method-override') , morgan = require('morgan') , errorhandler = require('errorhandler'); const { connect } = require('http2'); const app = express() app.set('views', __dirname + '/views') app.set('view engine', 'jade') app.use(methodOverride()) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })) app.use(express.static(path.join(__dirname, 'public'))) app.set('connection', mysql.createConnection({ host: process.env.RDS_HOSTNAME, user: process.env.RDS_USERNAME, password: process.env.RDS_PASSWORD, port: process.env.RDS_PORT})); function init() { app.get('/', routes.index); app.get('/hikes', hike.index); app.post('/add_hike', hike.add_hike); } const client = app.get('connection'); async.series([ function connect(callback) { client.connect(callback); console.log('Connected!'); }, function clear(callback) { client.query('DROP DATABASE IF EXISTS mynode_db', callback); }, function create_db(callback) { client.query('CREATE DATABASE mynode_db', callback); }, function use_db(callback) { client.query('USE mynode_db', callback); }, function create_table(callback) { client.query('CREATE TABLE HIKES (' + 'ID VARCHAR(40), ' + 'HIKE_DATE DATE, ' + 'NAME VARCHAR(40), ' + 'DISTANCE VARCHAR(40), ' + 'LOCATION VARCHAR(40), ' + 'WEATHER VARCHAR(40), ' + 'PRIMARY KEY(ID))', callback); }, function insert_default(callback) { const hike = {HIKE_DATE: new Date(), NAME: 'Hazard Stevens', LOCATION: 'Mt Rainier', DISTANCE: '4,027m vertical', WEATHER:'Bad', ID: '12345'}; client.query('INSERT INTO HIKES set ?', hike, callback); } ], function (err, results) { if (err) { console.log('Exception initializing database.'); throw err; } else { console.log('Database initialization complete.'); init(); } }); module.exports = app
  5. 將下列內容新增至 routes/hike.js。這將使路由能夠將新的登山日誌插入HIKES資料庫。

    const uuid = require('node-uuid'); exports.index = function(req, res) { res.app.get('connection').query( 'SELECT * FROM HIKES', function(err, rows) { if (err) { res.send(err); } else { console.log(JSON.stringify(rows)); res.render('hike', {title: 'My Hiking Log', hikes: rows}); }}); }; exports.add_hike = function(req, res){ const input = req.body.hike; const hike = { HIKE_DATE: new Date(), ID: uuid.v4(), NAME: input.NAME, LOCATION: input.LOCATION, DISTANCE: input.DISTANCE, WEATHER: input.WEATHER}; console.log('Request to log hike:' + JSON.stringify(hike)); req.app.get('connection').query('INSERT INTO HIKES set ?', hike, function(err) { if (err) { res.send(err); } else { res.redirect('/hikes'); } }); };
  6. routes/index.js 的內容取代為:

    /* * GET home page. */ exports.index = function(req, res){ res.render('index', { title: 'Express' }); };
  7. 將以下 Jade 範本新增至 views/hike.jade,以提供用於新增增長日誌的使用者介面。

    extends layout block content h1= title p Welcome to #{title} form(action="/add_hike", method="post") table(border="1") tr td Your Name td input(name="hike[NAME]", type="textbox") tr td Location td input(name="hike[LOCATION]", type="textbox") tr td Distance td input(name="hike[DISTANCE]", type="textbox") tr td Weather td input(name="hike[WEATHER]", type="radio", value="Good") | Good input(name="hike[WEATHER]", type="radio", value="Bad") | Bad input(name="hike[WEATHER]", type="radio", value="Seattle", checked) | Seattle tr td(colspan="2") input(type="submit", value="Record Hike") div h3 Hikes table(border="1") tr td Date td Name td Location td Distance td Weather each hike in hikes tr td #{hike.HIKE_DATE.toDateString()} td #{hike.NAME} td #{hike.LOCATION} td #{hike.DISTANCE} td #{hike.WEATHER}
  8. 使用 eb deploy 命令部署變更。

    ~/nodejs-example-express-rds$ eb deploy

清除

如果您已完成使用 Elastic Beanstalk,您可終止環境。

使用 eb terminate 命令來終止您的環境及其中的所有資源。

~/nodejs-example-express-rds$ eb terminate The environment "nodejs-example-express-rds-env" and all associated instances will be terminated. To confirm, type the environment name: nodejs-example-express-rds-env INFO: terminateEnvironment is starting. ...