Logo
Published on

[Github Action] Backup database tự động

Authors

Vấn đề

Hi anh em Dev, việc backup cơ sở dữ liệu là vấn đề cần thiết cho bất kỳ dự án nào, nó giúp chúng ta khôi phục lại dữ liệu nếu cơ sở dữ liệu chính gặp sự cố 🤤

Mình đang có 1 project cá nhân mà dữ liệu < 100MB, và mình tìm một giải pháp để backup thường xuyên, có thể 1 ngày backup 1 lần và chi phí tối ưu nhất

Chợt mình nảy ra ý tưởng có thể dùng Github action được không?

Phác thảo ý tưởng

Sau một hồi tìm hiểu thì mình thấy có thể thực hiện được, do Github Action có hỗ trợ chạy Scheduled Job, điều đó nghĩa là cứ sau mỗi khoản thời gian thì Github Action sẽ tự động trigger để chạy workflow.

Rồi như thế Github Action làm thế nào để backup được dữ liệu trong Database?

Gợi nhớ trong đầu về việc trước đây mình có tìm hiểu thì Github Action có thể tự động thay đổi version trong package.json và tự động commit vào repository.

Mà mình dùng MongoDB, và trong DB có vài collection.

May mắn sao mình tìm hiểu thấy trên Github Action có thể chaỵ được code, trong code thì mình kết nối đến database cần backup, sau đó lưu dữ liệu về file .json, mỗi collection sẽ là 1 file json riêng.

Bắt đầu triển khai thôi nào!!

Code script backup dữ liệu bằng NodeJS

Trước khi bạn tạo script này hãy tạo 1 repository trên Github để chứa script và dữ liệu backup nhé

Script này cũng đơn giản, chỉ cần kết nối đến database, query data và lưu dữ liệu vào folder backup

const { MongoClient } = require("mongodb");
const fs = require("fs");
const path = require("path");
require("dotenv").config();

const databases = [
  {
    uri: process.env.DB1_URI,
    dbName: "test", // biến này cũng có thể đưa ra .env luôn mà mình lười quá chưa sửa lại :]]
  }
];

async function backupDatabase(uri, dbName) {
  const client = new MongoClient(uri, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  });

  try {
    await client.connect();
    console.log(`Connected to MongoDB: ${dbName}`);

    const db = client.db(dbName);
    const collections = await db.collections();

    for (let collection of collections) {
      const collectionName = collection.collectionName;
      const data = await collection.find().toArray();

      const directoryPath = path.join(__dirname, `backup/${dbName}`);
      if (!fs.existsSync(directoryPath)) {
        fs.mkdirSync(directoryPath);
      }

      const filePath = path.join(`${directoryPath}`, `${collectionName}.json`);
      fs.writeFileSync(filePath, JSON.stringify(data, null, 2));

      console.log(
        `Backup for collection ${collectionName} in database ${dbName} completed. Saved to ${filePath}`
      );
    }

    console.log(`Backup completed for database ${dbName}.`);
  } catch (err) {
    console.error(`Error during backup for database ${dbName}:`, err);
  } finally {
    await client.close();
  }
}

async function backupAllDatabases() {
  for (let { uri, dbName } of databases) {
    await backupDatabase(uri, dbName);
  }
}

backupAllDatabases();

Tiếp đến cần tạo workflow để Github Action tự động trigger quá trình backup data

Tạo file workflow cho Github Action

Trong repository tạo đường dẫn .github/workflows, và tạo file deploy.yaml.

Trong file deploy.yaml mình sẽ cấu hình trigger theo 2 cách là schedule và workflow dispatch, trong trigger schedule thì cấu hình mỗi 8 tiếng sẽ chạy một lần (*/8 có nghĩa là mốc giờ chia hết cho 8). Còn sử dụng thêm workflow dispatch để bạn có thể chạy manual bằng cách vào Action trên Github để trigger nhé

name: Backup main db

on:
  schedule:
    - cron: '0 */8 * * *'
  workflow_dispatch:

jobs:
  run_and_commit:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '21'

    - name: Run Node.js script
      run: node main.js

    - name: Commit changes
      run: |
        git config --local user.name "github-actions[bot]"
        git config --local user.email "github-actions[bot]@users.noreply.github.com"
        git add -A
        git commit -m "Auto-commit: update from GitHub Actions"
        git push
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Như vậy đã xong quá trình deploy lên k8s sử dụng nodejs, các bạn có thắc mắc cứ comment bên dưới nha 🥰