AWS EC2 + LAMPP + Nodejs + Nginx 部署過程


Posted by Christy on 2022-02-17

本文為 Lidemy 程式導師計畫 W18 部署過程紀錄,採用 AWS EC2 + LAMPP + Nodejs + Nginx 部署使用 Express + Sequelize 所改寫的餐廳網站。此紀錄的目的是,下次再碰到同樣的過程,可以方便喚起記憶,從跌倒的地方再次開始。

零、內容摘要

1. AWS 開主機

2. 設置環境

3. 設置資料庫

4. 設定防火牆

5. 安裝 Nginx & PM2

6. 設定子網域

7. 安裝專案執行環境 + 上傳網頁檔案

8. 其他

一、AWS 開主機,參考 部署: AWS EC2 + LAMP + phpmyadmin + Filezilla,基本操作都一樣,這裡想要提醒自己:

1. AWS 超過 110 天不用,主機會自動被刪除。

2. key.pem 要保存好,如果不確定的話,最保險是重開新的。

3. security group 不要用 aws 的 default,自己設定 ssh/http/https/mysql ,取好記的名字比較方便,例如這次部署我取名 aws-lidemy。

4. 不確定檔案路徑,直接把檔案拖進 terminal 會自動生成路徑。

5. 隨時整理檔案,並小心取名,過多檔案難管理,也容易混亂。

二、設置環境

1. 連線進遠端主機:$ ssh -i ~/path/key.pem ubuntu@IPv4,此時的位置在 /home/ubuntu 底下

註:如有錯誤訊息 Permissions 0644 for '/Users/christy/key.pem' are too open. -> $ chmod 400 /Users/christy/key.pem

Debug: Aws connection problem

2. 更新 ubuntu 系統

$ sudo apt update && sudo apt upgrade && sudo apt dist-upgrade

3. 安裝 tasksel

$ sudo apt install tasksel

4. 用 tasksel 安裝 lamp-server

$ sudo tasksel install lamp-server

5. 測試 server

把 IPv4 貼到網址列,有出現 'Apache2 ubuntu default page' 代表成功

三、設置資料庫:安裝 phpmyadmin 在遠端主機裡

1. 安裝 phpmyadmin:

$ sudo apt install phpmyadmin

2. Configuring phpmyadmin:

按空白鍵選 apache2

3. 設定 phpmyadmin 管理員密碼

接下來會設置兩次密碼,建議自己都設一樣並記下來

4. 改變 phpmyadmin 登入方式,變成用密碼登入

帳號:root / 密碼:下面接著設定

a. 先用管理員身份登入 mysql: $ sudo mysql -u root mysql

b. 讓 root 可以用密碼登入:

mysql> UPDATE user SET plugin='mysql_native_password' WHERE User='root';

c. 更新權限:mysql> FLUSH PRIVILEGES;

d. 離開:mysql> exit

註:如有錯誤訊息:phpMyAdmin access denied for user 'root'@'localhost' (using password: YES)

解法:$ sudo nano /etc/phpmyadmin/config-db.php,帳號理論上會是 root,一定要改成 root 才可以。

有時會出現使用者是 phpmyadmin,每次都檢查比較保險,改完使用者變成 root 以後,再執行以下步驟會比較好。

PS 可以用  ctrl s 存檔,ctrl x 離開。

5. 設定 root 密碼

$ sudo mysql_secure_installation

全選 y,唯獨 'Disallow root login remotely?' 可以選 n,最後 All Done 表示完成。

6. 登入 MySQL

方法 1:

a. $ mysql -u root -p

b. 輸入密碼

c. 新增資料庫

CREATE DATABASE `db_name`;

方法 2:

在瀏覽器輸入 IPv4/phpmyadmin,以 root/剛剛設的密碼登入

PS mac 可用 Sequel Pro,如有連線問題,先登入 phpmyadmin,到「資料庫叫做 phpmyadmin」的權限裡面,把 root 權限 -> 登入資訊 -> 主機選任何主機,改好就可以登入了。

四、設定防火牆

1. $ sudo nano /etc/default/ufw: 確認 IPv6 = yes

2. 把 aws Security Groups 設定的 port 都打開

$ sudo ufw allow ssh

$ sudo ufw allow 443

$ sudo ufw allow 3306

$ sudo ufw allow 80

$ sudo ufw allow 22

註:這裡只能一個個輸入

3. 看防火牆開了哪些 port $ sudo ufw status verbose

4. 開啟防火牆 $ sudo ufw enable

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y

五、安裝 Nginx & PM2

a. 安裝 Nginx

$ sudo apt update
$ sudo apt install nginx

b. 啟動 Nginx:$ sudo systemctl start nginx

通常會有錯誤訊息:

error: Job for nginx.service failed because the control process exited with error code.

See "systemctl status nginx.service" and "journalctl -xe" for details.

c. 看 Nginx 的狀態: $ sudo systemctl status nginx

Active: failed (Result: exit-code) since Mon 2022-02-21 02:24:48 UTC;

Feb 21 02:24:48 ip-172-31-2-249 systemd[1]: Failed to start A high performance

Feb 21 02:24:48 ip-172-31-2-249 systemd[1]: Failed to start A high performance web server and a reverse

註:如有啟動錯誤,參考下方解法

$ sudo apt install net-tools
$ sudo netstat -tulpn // 看 Active Internet connections
$ sudo lsof -i:80 看誰在跑 80 port
有兩個方法,一個是刪掉,一個是關掉

$ sudo fuser -k 80/tcp 
// 刪除 80 port 目前的 connection;fuser 可改 kill

$ sudo service apache2 stop
// 直接關掉 apache2 (通常刪除 80 port 沒用)

$ sudo systemctl restart nginx
$ sudo systemctl status nginx
// 有 active 就成功了

d. 開啟防火牆:$ sudo ufw allow 'Nginx HTTP'

或直接去 ec2 改 security group 中的 inbounds rule

可以看防火牆的狀況:$ sudo ufw status

e. site-available 新增設定檔內容(子網域要連到哪個 port 去)

$ cd /etc/nginx/sites-available

建設定檔,可以取名跟網址一樣,如 just-a-bite.christy.tw

$ sudo vim just-a-bite.christy.tw

server {
        listen      80;
        server_name just-a-bite.christy.tw;
        location {
         proxy_pass http://127.0.0.1:5001;
        }
}

:wq 存檔離開

f. 連接 sites-available 和 site-enabled:

$ sudo ln -s /etc/nginx/sites/available/just-a-bite.christy.tw /etc/nginx/sites-enabled/

怎麼看有沒有連到?

$ cd /etc/nginx/sites-enabled/
ls -al

just-a-bite.christy.tw -> /etc/nginx/sites/available/just-a-bite.christy.tw

原本有這個:default -> /etc/nginx/sites-available/default

$ sudo unlink /etc/nginx/sites-enabled/default

g. 重啟 Nginx:$ sudo systemctl reload nginx

註:看 Nginx 錯誤訊息 $ sudo nginx -t

h. 瀏覽器輸入指定的子網域,如果有顯示即連結成功。

Nginx bug 解不開

nginx: [emerg] open() "/etc/nginx/sites-enabled/just-a-bite.christy.tw" failed (2: No such file or directory) in /etc/nginx/nginx.conf:62

nginx: configuration file /etc/nginx/nginx.conf test failed

移除 Nginx 再安裝一次

  1. $ sudo apt-get remove nginx nginx-common

  2. $ sudo apt-get purge nginx nginx-common

  3. $ sudo apt-get autoremove

  4. $ sudo apt-get install nginx

  5. $ sudo systemctl start nginx

  6. $ sudo systemctl status nginx,有 active 就成功了

Pm2

1. 安裝:$ sudo npm install pm2 -g

2. pm2 ls:看 PM2 有跑哪些東西

3. pm2 start index.js:在相對應資料夾底下執行,可以跑寫好的程式

輸入熟悉的網址 http://localhost:5001/,就跑起來了。

測試

$ node index.js

用剛剛的網址,有連上就代表部署成功

六、設定子網域

去 gandi 設定子網域

  1. 點擊域名,選擇區域檔紀錄

  2. 新增類型 A

  3. 取名稱子網域

  4. IPv4 = AWS 的 IPv4

  5. 完成

七、安裝專案執行環境

在 /var/www/html 下新增資料夾,本地安裝的所有東西都裝在這

1. $ cd /var/www/html

2. 新增資料夾 bite:$ sudo mkdir bite

3. $ sudo chown ubuntu /var/www/html/bite

4. $ cd /var/www/html/bite

5. 安裝專案執行環境

a. 個人喜歡,可不裝 $ sudo apt install tree

b. $ sudo apt install npm

c. $ npm init -y

d. $ npm install express

e. $ npm install ejs express-session connect-flash bcrypt

f. $ npm install sequelize mysql2

註:在 npm v5.0.0 之後,--save 已經成為預設指令,所以把以前舊筆記寫的 —save 拿掉了

g. $ npm install sequelize-cli

不應該用這個指令 $ npm install --save-dev sequelize-cli --dev 是指開發限定使用,比如說 SASS,開發完以後就不用了。但我這裡的東西部署也要用,所以不該下 --dev。

h. $ npx sequelize-cli init

i. $ npm install dotenv

6. 上傳網頁檔案

a. 上傳檔案

// 上傳前結構
.
├── config
├── migrations
├── models
├── node_modules
├── package-lock.json
├── package.json
└── seeders
// 上傳 config、controllers、public、views、.env、index.js、.sequelizerc
.
├── config
├── controllers
├── index.js
├── migrations
├── models
├── node_modules
├── package-lock.json
├── package.json
├── public
├── seeders
├── .env
├── .sequelizerc
└── views

b. 建立 models

1. 抽獎:item, content, url, ratio

$ npx sequelize-cli model:generate --name Prize --attributes item:text,content:text,url:text,ratio:integer

2. 使用者:id, username, password, createdAt, updatedAt

$ npx sequelize-cli model:generate --name User --attributes username:string,password:string

3. 菜單:item, price, photo

$ npx sequelize-cli model:generate --name Menu --attributes item:string,price:integer,photo:string

4. 訂單:po, item, quantity, price, amount, freight, status

$ npx sequelize-cli model:generate --name Order --attributes po:string,item:string,quantity:integer,price:integer,amount:integer,freight:integer,status:string

5. 問答:sequence, title, content

$ npx sequelize-cli model:generate --name Question --attributes sequence:integer,title:string,content:text

註:在下個步驟以前,一定要先設好資料庫,建立 3306 port 的連線,不然會出現失敗訊息

c. Running Migrations $ npx sequelize-cli db:migrate

註:這裡有錯的話,通常是環境變數沒有設好,參考以下設定。

如果不確定,可以去 $ sudo nano /etc/phpmyadmin/config-db.php 看一下裡面的資料

// .env

PORT=5001

DEV_USERNAME=
DEV_PASSWORD=
DEV_HOST=
DEV_DATABASE=

PROD_USERNAME=通常是 root
PROD_PASSWORD=
PROD_HOST=寫 localhost
PROD_DATABASE=

SESSION_SECRET=

八、其他

沒有關掉終端機,隔天再操作時,會需要輸入 ubuntu 密碼,把終端機關掉重新連線就好了。










Related Posts

[SQL] Update Where 依照條件更新指定欄位

[SQL] Update Where 依照條件更新指定欄位

[重新理解C++] 從 function object 理解惰性編譯

[重新理解C++] 從 function object 理解惰性編譯

Day 157

Day 157


Comments