用 Docker 每天自動化備份 MySQL, Postgres 或 MongoDB 並上傳到 AWS S3

由於備份 PostgreSQL 的指令 pg_dump 需要限定特定版本才可以備份,故自己製作用 Docker 容器方式來備份,此工具支援 MySQL, PostgreSQL 跟 MongoDB,只要一個 docker-compose yaml 檔案就可以進行線上的備份,並且上傳到 AWS S3,另外也可以設定每天晚上固定時間點進行時間備份,也就是平常所設定的 cron job。沒使用 AWS RDS,或自行管理機房的朋友們,就可以透過這小工具,進行每天半夜線上備份,避免資料被誤砍。底下教學程式碼都可以在這邊找到

影片教學

  • 00:00 備份資料庫工具介紹
  • 00:40 為什麼要寫這工具?
  • 01:55 架設 Minio S3 Storage 服務
  • 02:56 Minio UI 介面介紹 (建立 bucket)
  • 03:32 架設 PostgreSQL 12 服務
  • 04:00 備份方式參數介紹
  • 07:06 執行備份程式
  • 09:18 設定 Minio 內的 bucket life cycle (只保留七天內資料)
  • 10:25 設定每天自動備份並上傳到 Minio S3

如果對於課程內容有興趣,可以參考底下課程。

如果需要搭配購買請直接透過 FB 聯絡我,直接匯款(價格再減 100

使用方式

本教學使用 Minio 來代替 AWS S3,底下用 docker-compose 來架設 Minio 及 PostgreSQL 12 版本

services:
  minio:
    image: minio/minio:edge
    restart: always
    volumes:
      - data1-1:/data1
    ports:
      - 9000:9000
    environment:
      MINIO_ACCESS_KEY: 1234567890
      MINIO_SECRET_KEY: 1234567890
    command: server /data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  postgres:
    image: postgres:12
    restart: always
    volumes:
      - pg-data:/var/lib/postgresql/data
    logging:
      options:
        max-size: "100k"
        max-file: "3"
    environment:
      POSTGRES_USER: db
      POSTGRES_DB: db
      POSTGRES_PASSWORD: db

接著挑選特定資料庫版本的 Docker Image

  backup_postgres:
    image: appleboy/docker-backup-database:postgres-12
    logging:
      options:
        max-size: "100k"
        max-file: "3"
    environment:
      STORAGE_DRIVER: s3
      STORAGE_ENDPOINT: minio:9000
      STORAGE_BUCKET: test
      STORAGE_REGION: ap-northeast-1
      STORAGE_PATH: backup_postgres
      STORAGE_SSL: "false"
      STORAGE_INSECURE_SKIP_VERIFY: "false"
      ACCESS_KEY_ID: 1234567890
      SECRET_ACCESS_KEY: 1234567890

      DATABASE_DRIVER: postgres
      DATABASE_HOST: postgres:5432
      DATABASE_USERNAME: db
      DATABASE_PASSWORD: db
      DATABASE_NAME: db
      DATABASE_OPTS:

其中 STORAGE_BUCKET 是 AWS S3 的 bucket 名稱,還有需要設定 STORAGE_PATH 這樣待會可以設定 bucket lifecycle,可以設定幾天後刪除舊的資料,接著設定 Minio S3 的 bucket lifecycle:

$ mc ilm import minio/test <<EOF
{
    "Rules": [
        {
            "Expiration": {
                "Days": 7
            },
            "ID": "backup_postgres",
            "Filter": {
                "Prefix": "backup_postgres/"
            },
            "Status": "Enabled"
        }
    ]
}
EOF

上面設定是一次性的備份,也就是手動使用 docker-compose up backup_postgres 就可以進行一次備份,當然可以固定每天晚上時間來備份

  backup_mysql:
    image: appleboy/docker-backup-database:mysql-8
    logging:
      options:
        max-size: "100k"
        max-file: "3"
    environment:
      STORAGE_DRIVER: s3
      STORAGE_ENDPOINT: minio:9000
      STORAGE_BUCKET: test
      STORAGE_REGION: ap-northeast-1
      STORAGE_PATH: backup_mysql
      STORAGE_SSL: "false"
      STORAGE_INSECURE_SKIP_VERIFY: "false"
      ACCESS_KEY_ID: 1234567890
      SECRET_ACCESS_KEY: 1234567890

      DATABASE_DRIVER: mysql
      DATABASE_HOST: mysql:3306
      DATABASE_USERNAME: root
      DATABASE_PASSWORD: db
      DATABASE_NAME: db
      DATABASE_OPTS:

      TIME_SCHEDULE: "@daily"
      TIME_LOCATION: Asia/Taipei

TIME_LOCATION 可以設定台灣時區,不然預設會是 UTC+0 時間。更多詳細的設定可以參考文件

心得

由於本身團隊可能沒有使用 AWS RDS 服務,故自己都需要寫程式自行備份,但是同事用的 DB 都不同,所以乾脆包成 Docker 容器方式讓同事可以方便設定。之後有新專案就可以直接套用,相當容易。