本文為 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
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 再安裝一次
$ sudo apt-get remove nginx nginx-common
$ sudo apt-get purge nginx nginx-common
$ sudo apt-get autoremove
$ sudo apt-get install nginx
$ sudo systemctl start nginx
$ 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 設定子網域
點擊域名,選擇區域檔紀錄
新增類型 A
取名稱子網域
IPv4 = AWS 的 IPv4
完成
七、安裝專案執行環境
在 /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 密碼,把終端機關掉重新連線就好了。