本文詳細介紹如何部署NodeJS專案到阿里雲ECS上,以及本人在部署過程中所遇到的問題、坑點和解決辦法,可以說是全網最全最詳細的教程了。同時講解了如何申請阿里雲免費SSL證書,以及一臺ECS伺服器配置多網站的Nginx配置方法等。

作者:Kovli

1. 雲伺服器選擇

阿里雲ECS是阿里巴巴旗下,目前國內最成熟穩定的雲伺服器提供商

本文基於阿里雲ECS雲伺服器講解,目前有個人版,企業版,學生版可以選擇。

個人版 2折優惠活動,一年293元起,平均下來一個月20多即可擁有屬於自己的伺服器了。

學生版 一個月9.5,24歲以下自動獲得學生身份,學生推薦這個伺服器。

企業版 效能強大,有2-5折的活動。

優惠券 阿里雲產品通用代金券最高1000元。

這裡以個人版 為例,流程都一樣的。

選購好雲伺服器,初學者1核1G就足夠了,也就是預設的第一個入門級配置。

作業系統選擇CentOS系統

image

點選立即購買按鈕,進入確認訂單頁面,這裡選擇自定義密碼,設定ssh登入密碼,後面要用,請牢記此密碼

image

購買好以後,進入控制檯,左側功能欄選擇雲伺服器ECS

image

點選箭頭所指位置,即可獲取伺服器的公網地址,如圖

image 記住公網IP,下一步要用到。

2. 登陸伺服器

開啟 Terminal,

輸入 ssh [email protected]公網IP

輸入之前自己設的伺服器登入密碼(如果忘了,可以去上圖右側的管理-更多-重置密碼)

即可登陸伺服器。

首次登陸可能會詢問公鑰,yes 即可。

關於 ssh 登陸,想要詳細瞭解的可以看阮一峰寫的這篇ssh原理與應用

上述操作是使用 root 使用者身份登陸,會直接進入到下圖 紅色箭頭標出的 root 目錄下。

cd .. 跳轉到上一層, 再 ls -a ,就可以看到類似下圖的目錄結構了。

image 圖片引用自《鳥哥的Linux》

3. 安裝Nginx

1. 在配置 nginx 時,可能會依賴於 PCRE 包和 zlib 包,先進行安裝:

cd /usr/local 切換目錄

cd /usr/local
yum -y install pcre pcre-devel
yum install -y zlib-devel

2. 下載 nginx,這裡nginx版本號可以根據需要選擇,我選擇1.13.3是當時最新的版本了,下面的node版本、mongodb版本都可以根據自己的需要選擇

cd /usr/local/src 
wget http://nginx.org/download/nginx-1.13.3.tar.gz

3. 解壓縮

tar -xvzf nginx-1.13.3.tar.gz

4. 配置nginx

下載解壓openssl

wget https://www.openssl.org/source/openssl-1.0.2l.tar.gz

tar -xvzf openssl-1.0.2l.tar.gz 

cd 進入nginx解壓包裡,執行之前安裝的pcre-devel與openssl-devel解決依賴問題

cd nginx-1.13.3
yum -y install pcre-devel openssl openssl-devel

再執行配置指令碼來進行編譯預處理

./configure --prefix=/usr/local/nginx --conf-path=/usr/local/nginx/nginx.conf --with-http_stub_status_module --with-http_gzip_static_module --with-http_ssl_module --with-openssl=/usr/local/src/openssl-1.0.2l

成功後顯示如下資訊,

Configuration summary
  + using system PCRE library
  + using OpenSSL library: /usr/local/src/openssl-1.0.2l
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx"
  nginx configuration file: "/usr/local/nginx/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

make

make && make install

5. 使用 openssl 生成證書(以下介紹的是自己生成的供學習用,正常面向市場的產品請用認證的)

openssl req -new -x509 -nodes -out server.crt -keyout server.key

移動證書到nginx資料夾

mv server.crt /usr/local/nginx
mv server.key /usr/local/nginx

認證的SSL證書,申請阿里雲免費ssl證書:

操作技巧:想看到免費的證書,品牌選擇Symantec,證書型別選擇免費型DV SSL

6. 修改 nginx 配置檔案:

vi /usr/local/nginx/nginx.conf

修改如下


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    # 關閉錯誤頁面的nginx版本數字,提高安全性
    server_tokens off;

    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    include /usr/local/nginx/sites-enabled-server/*;


}

新建資料夾用於存放多網站的nginx配置檔案

cd /usr/local/nginx/
mkdir sites-enabled-server

sites-enabled-server裡面新增若干檔案,以便這個ECS可以給多網站使用

vim default


server {
        listen 80;
        server_name _;

        return 404;
}

server {
        listen       80;
        server_name  你的域名.com www.你的域名.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://127.0.0.1:nodejs配置的埠號;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

vim default-ssl

server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      server.crt;
        ssl_certificate_key  server.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
             proxy_pass http://127.0.0.1:nodejs配置的埠號;
        }
    }
~       
server {
        listen       80;
        server_name  mywebsite.cn www.mywebsite.cn;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://127.0.0.1:nodejs配置的mywebsite的埠號;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

7. 啟動nginx

/usr/local/nginx/sbin/nginx

4. 安裝 node

  • node – 編譯後二進位制檔案應在/usr/local/bin/node 下

  • mongodb – 安裝在/usr/local/mongodb 下

下面就一步一步來

1. 首先升級CentOS yum -y update

2. 升級後,跳轉到 /usr/local/src , 這個資料夾通常用來存放軟體原始碼

cd /usr/local/src

3. 下載 nodejs 程式碼,也可以使用scp命令直接上傳,因為下載實在太慢了。

wget http://nodejs.org/dist/node-latest.tar.gz(下載最新)
wget http://nodejs.org/dist/v7.10.0/node-v7.10.0.tar.gz(推薦,穩定版本)

4. 解壓 tar -xzvf node-v0.12.5.tar.gz

5. 進入解壓後的資料夾 cd node-v0.12.5

6. 執行配置指令碼來進行編譯預處理 ./configure

7. 安裝v8可能有警告, //需要安裝gcc

8. sudo yum install gcc-c++ //安裝gcc

9. 編譯原始碼及安裝

當編譯完成後,需要使之在系統範圍內可用, 編譯後的二進位制檔案將被放置到系統路徑,預設情況下,Node二進位制檔案應該放在/user/local/bin/node資料夾下

make && make install

10. 安裝pm2,建議 global 安裝 npm install pm2 -g

11. 建立超級連結, 不然 sudo node 時會報 "command not found"

  • sudo ln -s /usr/local/bin/node /usr/bin/node
  • sudo ln -s /usr/local/lib/node /usr/lib/node
  • sudo ln -s /usr/local/bin/npm /usr/bin/npm
  • sudo ln -s /usr/local/bin/node-waf /usr/bin/node-waf
  • sudo ln -s /usr/local/bin/pm2 /usr/bin/pm2

Nodejs到這裡就基本安裝完成了。

5. 安裝mongodb

  • 軟體安裝位置:/usr/local/mongodb

  • 資料存放位置:/var/mongodb/data

  • 日誌存放位置:/var/mongodb/logs

1. 首先下載安裝包

cd /usr/local
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.6.tgz

2. 解壓安裝包,重新命名資料夾為mongodb

tar zxvf mongodb-linux-x86_64-2.6.0.tgz
mv mongodb-linux-x86_64-2.6.0 mongodb

3. 建立資料和日誌存放目錄

mkdir /var/mongodb
mkdir /var/mongodb/data
mkdir /var/mongodb/logs

4. 開啟rc.local檔案,新增CentOS開機啟動項:

vim /etc/rc.d/rc.local

5. 將mongodb啟動命令追加到本檔案中,讓mongodb開機自啟動:

/usr/local/mongodb/bin/mongod --dbpath=/var/mongodb/data --logpath /var/mongodb/logs/log.log --logappend --auth --port 27017 --fork

6. mongo許可權設定

sudo vi /etc/mongod.conf

較新版本的增加安全校驗的方法是配置檔案最後面加上(網上很多舊版寫法都是無效的)

security: authorization: enabled

如下所示:

systemLog:
 destination: file
 path: /var/mongodb/logs/log.log
 logAppend: true
storage:
 dbPath: /var/mongodb/data
net:
 bindIp: 127.0.0.1
security:
 authorization: enabled

然後重啟mongodb即可,這裡說明下,初學也可以不設這個選項,這樣操作資料庫就不需要使用者名稱密碼了,從安全的角度看還是設了比較好,後面都是以設了安全校驗來講解。

7. 關閉 vim 後,直接手動啟動mongodb

/usr/local/mongodb/bin/mongod --dbpath=/var/mongodb/data --logpath /var/mongodb/logs/log.log --logappend --auth --port 27017 --fork

8. 啟動mongo shell

cd /usr/local/mongodb/bin/
./mongo

9. 在 mongo shell 中建立超級管理員以及相關資料庫到管理員及資料庫

use admin //admin database
db.createUser({
 user: "myAdmin",
 pwd: "******",
 roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
 }
 )

10. 使用特權進入

./mongo -u "mydmin" -p "******" --authenticationDatabase "admin"

11. 建立新資料庫,並設定管理員

> use mywebsite
switched to db mywebsite
> db.createUser(
... {
... user: "mywebsiteAdmin",
... pwd: "******",
... roles: [ { role: "readWrite", db: "mywebsite" }]
... }
... )
> use secondwebsite
switched to db secondwebsite
> db.createUser(
... {
... user: "secondwebsiteAdmin",
... pwd: "******",
... roles: [ { role: "readWrite", db: "secondwebsite" }]
... }
... )

以後進入其中的資料庫需要許可權,如果用超級管理員則不需要

db.auth("mywebsiteAdmin", "******")

12. mongodb資料遷移(用於從指定地址資料庫遷移到雲伺服器上)

//存放到某個目錄
./mongodump -h 127.0.0.1:27017 -d mywebsite -o /home/mywebsite -u "mywebsiteAdmin" -p "******"

//取出
./mongorestore  -h 127.0.0.1:27017 -d mywebsite /home/mywebsite/mywebsite -u "mywebsiteAdmin" -p "******"

13. mongodb連線需要安全校驗的配置 以app.js為例,

設定資料庫連線 vim app.js

資料庫連線類似下面的格式,由於資料庫安裝在同一伺服器,因此 host 為127.0.0.1:

var dbUrl = 'mongodb://使用者名稱:登陸密碼@127.0.0.1/databaseFoo';
mongoose.connect(dbUrl)

例如我的app.js裡的這一段程式碼

// 配置資料庫
mongoose.Promise = global.Promise;
let mongoConnectUrl = 'mongodb://' + config.database.USERNAME + ':' + config.database.PASSWORD + '@' + config.database.HOST;
mongoose.connect(mongoConnectUrl);

到這裡 mongodb 基本已經安裝設定完成了。

6. 上傳NodeJS程式碼到伺服器上

把nodejs的程式放在 /home

cd /home

我使用碼雲管理程式碼。它的私有庫是免費的。基本操作和 github 一樣。

1. 注意公鑰的生成與新增

ssh-keygen -t rsa -C "[email protected]"

檢視與複製公鑰

cat ~/.ssh/id_rsa.pub

2. git安裝

yum install git

3. 複製程式碼: git clone https://git.oschina.net/xxxxxxx/nodeapp.git //你的repo地址

4. 進入 nodeapp 資料夾 cd nodeapp (若後續程式碼變更,提交到 git repo 後直接git pull即可部署程式碼)

5. 安裝nodeapp的所有依賴

npm install

注意,使用淘寶映象避免未知問題

npm --registry https://registry.npm.taobao.org install

7. 啟動Node服務

這裡根據你nodejs所使用的框架不同而不同,

例如koa2可以在package.jsonscripts裡設定,參考阮一峰的npm scripts 使用指南

thinkjs或者egg都有自己的啟動方式,就不一一敘述了

這裡要注意的是,如果直接 npm startnode app.js 啟動,則一旦退出 ssh 遠端登陸,服務就會停止執行。

使用pm2就可以解決這個問題,如果跟著教程走,你已經全域性安裝了pm2了,可以直接使用

8. 其他說明

這篇文章是匯聚了網上諸多教程及本人從零開始部署遇到的各種問題和坑點的解決方案所形成的一篇詳細教程,由於涉及點比較多,加上版本更新迭代,如果在部署過程中遇到問題,可以在下面評論提問(需要登入Github賬號才可以評論),或者給我發郵件([email protected])。

本文所述的本地作業系統:MacOS系統,阿里雲ECS作業系統:CentOS 7.3,本地如果是Windows環境終端操作可能有所不同。

Nginx的一些常用操作方法:

/usr/local/nginx/sbin/nginx # 啟動
/usr/local/nginx/sbin/nginx -t #檢查配置檔案編寫是否正確
/usr/local/nginx/sbin/nginx -s reload #Nginx平滑重啟 (一般用這個就可以了)
/usr/local/nginx/nginx.conf #配置檔案。