投票系統部署與維護

目錄

簡介

這份筆記詳細說明投票系統的部署與維護方法,包括自動化部署腳本的工作原理、資料庫持久化存儲的機制,以及如何在代碼更新後重新部署系統。這套部署系統使用 Docker 和 Docker Compose 來管理前後端服務以及資料庫。

部署腳本詳解

部署腳本是一個 Node.js 程式,負責自動化投票系統的初始化和更新流程。

配置

腳本開始時定義了基本配置,包括前後端的 Git 倉庫地址:

const config = {
  frontendRepo: "http://192.168.100.202/warriors/voting-system-fe.git",
  backendRepo: "http://192.168.100.202/warriors/voteting-system-be.git",
};

日誌輸出

腳本使用彩色輸出來區分不同類型的日誌:

function log(message, type = "info") {
  const colors = {
    info: "\x1b[34m", // 藍色
    success: "\x1b[32m", // 綠色
    error: "\x1b[31m", // 紅色
    reset: "\x1b[0m", // 重置
  };

  console.log(`${colors[type]}${message}${colors.reset}`);
}

命令執行

腳本通過 runCommand 函數執行系統命令,並處理執行過程中可能發生的錯誤:

function runCommand(command, options = {}) {
  try {
    log(`執行命令: ${command}`, "info");
    return execSync(command, {
      stdio: "inherit",
      ...options,
    });
  } catch (error) {
    log(`命令執行失敗: ${error.message}`, "error");
    throw error;
  }
}

Dockerfile 創建

腳本會檢查並創建必要的 Dockerfile:

  1. 前端 Dockerfile

    • 使用 Node.js 環境構建前端應用

    • 使用 Nginx 作為靜態內容服務器

    • 包含自定義的 Nginx 配置以處理 API 代理和單頁應用路由

  2. 後端 Dockerfile

    • 使用 Node.js 環境

    • 安裝必要的構建工具

    • 設置 Prisma 客戶端

    • 使用啟動腳本來處理資料庫遷移和應用啟動

啟動腳本

腳本會創建一個後端啟動腳本 start.sh,用於在容器啟動時執行以下操作:

  • 等待資料庫就緒

  • 執行 Prisma 遷移

  • 啟動應用

啟動腳本的內容如下:

#!/bin/sh
# 等待資料庫就緒
echo "Waiting for database to be ready..."
sleep 5

# 執行遷移
echo "Running migrations..."
npx prisma migrate deploy

# 啟動應用
echo "Starting application..."
npm run dev

主程序流程

腳本的主要執行流程分為 7 個步驟:

  1. 檢查並更新前端專案

  2. 檢查並更新後端專案

  3. 檢查前端 Dockerfile

  4. 檢查後端 Dockerfile

  5. 創建啟動腳本

  6. 更新後端 Dockerfile 以使用啟動腳本

  7. 構建並啟動系統

這個流程確保了每次執行腳本時,系統都能獲取最新的代碼,並正確配置所有必要的文件。

資料持久化

Docker Compose 配置

投票系統使用 Docker Compose 來管理服務。docker-compose.yml 文件定義了三個主要服務:

version: '3.8'

services:
  db:
    image: postgres:13
    container_name: voting_db
    restart: always
    environment:
      TZ: Asia/Taipei
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: voting_system
    volumes:
      - ./data/:/var/lib/postgresql/data
    ports:
      - "15432:5432"

  server:
    build: 
      context: ./voting-system-be
    image: voting-system-be
    restart: always
    container_name: voting_system_be
    depends_on:
      - db
    environment:
      DATABASE_URL: "postgresql://postgres:postgres@db:5432/voting_system"
    ports:
      - "3000:3000"

  frontend:
    build: 
      context: ./voting-system-fe
    image: voting-system-fe
    container_name: voting_system_fe
    restart: always
    ports:
      - "4200:80"
    depends_on:
      - server

持久化原理

資料持久化主要通過 db 服務中的卷映射來實現:

volumes:
  - ./data/:/var/lib/postgresql/data

這行配置將宿主機上的 ./data/ 目錄映射到 PostgreSQL 容器內的資料存儲目錄。這確保了即使容器被刪除或重新構建,資料庫數據仍然保留在宿主機上的 ./data/ 目錄中。

當執行 docker-compose down 並重新啟動時,Docker 會重新創建容器,但會保留卷中的數據。這意味著您的資料庫數據在各次部署之間是持久存在的。

資料安全性

重要說明:

  • 部署腳本中的 docker-compose down 命令沒有使用 -v 參數,因此不會刪除卷中的數據

  • 如果您需要清空數據(例如在開發環境中),可以手動刪除 ./data/ 目錄的內容

  • 在生產環境中,應考慮定期備份 ./data/ 目錄以防資料丟失

專案更新流程

代碼更新

當您更改了代碼並合併到主分支(main)後,部署流程如下:

  1. 開發人員在本地修改代碼

  2. 提交並推送到遠程倉庫

  3. 通過 Pull Request 或直接推送,將變更合併到 main 分支

部署更新

合併完成後,在部署服務器上執行部署腳本:

  1. 執行部署腳本:node deploy.js(假設腳本名為 deploy.js)

  2. 腳本會自動執行以下操作:

    • 從遠程倉庫拉取最新的代碼(git pull origin main

    • 確保 Dockerfile 和配置文件是最新的

    • 重新構建並啟動 Docker 容器

重要的是,這個過程不會丟失任何資料庫數據,因為數據存儲在持久化卷中。

故障排除

如果部署過程中遇到問題:

  1. 檢查腳本輸出的錯誤訊息

  2. 查看 Docker 容器日誌:docker logs voting_system_bedocker logs voting_system_fe

  3. 檢查網絡連接和 Git 倉庫訪問權限

  4. 確保 Docker 和 Docker Compose 已正確安裝

常見問題

Q: 每次執行部署腳本時,資料會被清空嗎?

A: 不會。資料庫數據存儲在持久化卷中(./data/ 目錄),部署腳本執行 docker-compose down 時不會刪除這些數據。只有當您手動刪除 ./data/ 目錄或使用 docker-compose down -v 命令時,數據才會被清除。

Q: 如何在代碼更新後部署最新版本?

A: 只需執行部署腳本。腳本會自動拉取最新的代碼,重新構建容器,並啟動更新後的系統。這是整個設計的主要目的 - 簡化部署流程。

Q: 是否需要手動執行資料庫遷移?

A: 不需要。啟動腳本 start.sh 會在容器啟動時自動執行 npx prisma migrate deploy 命令,應用所有尚未應用的資料庫遷移。

Q: 為什麼 Prisma 遷移在容器內執行而不是直接在後端專案中執行?

A: 在容器內執行 Prisma 遷移有幾個重要優勢:

  • 環境一致性:確保遷移在與應用程式完全相同的環境中運行,避免環境差異導致的問題

  • 自動化部署:將遷移作為容器啟動過程的一部分,實現完全自動化的部署流程

  • 資料庫連接簡化:容器內服務可通過 Docker 網絡直接使用服務名稱(如 db)連接資料庫

  • 順序控制:啟動腳本確保了正確的執行順序:先等待資料庫就緒,再執行遷移,最後啟動應用

如果選擇在容器外執行遷移,您需要額外處理環境一致性、資料庫連接配置、手動執行命令以及維護執行順序等問題,這增加了部署的複雜性和出錯可能。

Q: 如何確保前端能正確連接到後端 API?

A: Nginx 配置文件中已設置了代理,將 /api 路徑的請求轉發到後端服務。這在前端 Dockerfile 中的 nginx.conf 已經配置好,確保前端應用能正確訪問 API。

Last updated