部署 Astro 專案到低配置的 Ubuntu 伺服器

程式設計 # Astro

這回 Astro 專案的開發,一開始選定了部署到 Netlify 上,結果正式站在上線之時卻意外掛掉,查了之後發現是 Astro 在 Netlify 使用 Session 時,依賴的 Netlify Blobs 卻有問題,無奈之下決定改用自架的 Ubuntu 伺服器來部署。

為了節省成本,這次專案給了超小的 Ubuntu 伺服器,只有 1G RAM,可是專案不是小專案,那不出意外的自然無法部署成功,因為跑 yarn build 時報了記憶體不足的錯誤 (這還是我頭一回見到 Node.js 中的記憶體不足的錯誤XDD)。後來我就研究了一個方法,先在本地 WSL 內編譯好,再把編譯好的檔案用 SFTP 傳到伺服器上,這樣就可以成功部署了~

在 Ubuntu 伺服器上可以直接用 Node.js 的部署方式,使用 Nginx 作反向代理,並用 pm2 來管理 Astro 的 Node.js 服務。

Nginx 反向代理設定

Nginx 只要負責反向代理的部分就行了,以下是 Nginx 設定範例:

/etc/nginx/sites-available/your-domain.conf
server {
listen 80;
listen [::]:80;
server_name your-domain;
server_tokens off;
root /var/www/html;
index index.html;
charset utf-8;
location / {
proxy_pass http://localhost:4321;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
}

手動部署專案

在本地編譯和上傳檔案:

Terminal window
# remote: 重建 dist 資料夾
rm dist -rf && mkdir dist
# local: 編譯和上傳檔案
yarn
yarn build
# 記得要設定全局變數
cp .env.example .env
sftp user@remote_host
> cd /var/www/html
> put -r dist
> bye

然後在伺服器上用 pm2 來啟動服務:

Terminal window
# remote: 安裝 pm2 並啟動服務
npm install -g pm2
pm2 start ./dist/server/entry.mjs --name app_name
pm2 startup
pm2 save
# remote: 重啟服務
pm2 list
pm2 restart app_name
# 或者是完全刪除再啟動
pm2 delete app_name
pm2 start ./dist/server/entry.mjs --name app_name

解除限制!自動化部署

後來這個專案合作的後端工程師找到了編譯時記憶體不足的解法,在執行 yarn build 時,增加 Node.js 的記憶體限制,這樣就可以直接在伺服器上編譯了,但這個數值還是不能超過實際上的記憶體上限呵呵:

Terminal window
NODE_OPTIONS="--max-old-space-size=1024" yarn build

如果可以在伺服器上直接編譯的話,就可以寫部署腳本來自動化部署了。這樣每次要更新網站時,只要把程式碼推到 GitHub 後,在伺服器上執行這個腳本就可以了:

deploy.sh
#!/bin/bash
git pull origin main
yarn
NODE_OPTIONS="--max-old-space-size=1024" yarn build
pm2 restart app_name

然後就可以 ssh 到伺服器上執行這個腳本來部署了:

Terminal window
# 使用 ssh 登入伺服器
ssh user@remote_host
cd /var/www/html
# 設定 git 不要處理檔案權限的變更,並給予 deploy.sh 執行權限
git config core.fileMode false
chmod +x deploy.sh
# 執行部署腳本
./deploy.sh