# Makefile: 適用於 docker-compose 專案,自動取用當前資料夾為專案名 COMPOSE := docker-compose COMPOSE_FILE := docker-compose.yml PROJECT_NAME := $(notdir $(CURDIR))  # 依照當前資料夾自動命名 # 資料庫服務名稱與 Volume 名稱 DB_SERVICE_NAME := db # 在 docker-compose.yml 中定義的資料庫服務名稱 (例如:db) # Docker Compose 預設會為 Volume 加上專案名稱前綴。 # 所以如果你的 Volume 叫 app_postgres_data,且專案名稱是 myproject, # 那實際的 Volume 名稱會是 myproject_app_postgres_data。 # 若為 standalone 的 docker-compose.yml (不指定 project name),則為 app_postgres_data。 DB_VOLUME_NAME := $(PROJECT_NAME)_app_postgres_data # 資料庫 Volume 的完整名稱 # 資料庫連線環境變數 (從 docker-compose.yml 的預設值同步過來,以確保備份還原時能正確連線) DB_USER ?= postgres # 若未從環境變數指定,預設為 postgres DB_NAME ?= app_db # 若未從環境變數指定,預設為 app_db DB_PASSWORD ?= password # 若未從環境變數指定,預設為 password # 備份檔案名稱與路徑 BACKUP_DIR := ./db_backups # 備份檔案存放的目錄 BACKUP_FILE := $(BACKUP_DIR)/$(shell date +%Y%m%d_%H%M%S)_$(PROJECT_NAME)_db_backup.sql # 可選自訂 .env 變數(預設 docker-compose 自動載入 .env 檔) # ENV_FILE := .env .PHONY: help up up-fg down build restart logs ps exec clean prune backup-db restore-db help: @echo "🔧 Docker Compose Makefile 指令:" @echo "  make up             - 啟動所有服務 (背景執行)" @echo "  make up-fg          - 前景執行(方便除錯)" @echo "  make down           - 停止並移除服務容器" @echo "  make build          - 重新建構服務映像檔" @echo "  make restart        - 重啟所有服務" @echo "  make logs           - 查看服務日誌" @echo "  make ps             - 顯示服務狀態" @echo "  make exec SERVICE   - 進入指定服務容器的 shell (預設:db)" @echo "  make clean          - 清理所有服務容器與相關 Volume (適合砍掉重練)" @echo "  make prune          - 清除未使用的 Docker 資源 (映像檔、網路、Volume)" @echo "" @echo "  make backup-db      - 備份 PostgreSQL 資料庫到 ./db_backups/" @echo "  make restore-db FILE - 還原 PostgreSQL 資料庫,FILE 是備份檔的完整路徑" @echo "                          範例: make restore-db FILE=./db_backups/20250624_011228_yourproject_db_backup.sql" @echo "" @echo "⚠️ 注意:'restore-db' 會清空目標資料庫後再還原,請謹慎使用。" up: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up -d up-fg: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up down: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) down build: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) build restart: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) down $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up -d logs: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) logs -f --tail=100 ps: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) ps # 預設進入 db 服務的 shell,也可以指定其他服務 exec: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(or $(SERVICE),$(DB_SERVICE_NAME)) bash clean: $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) down -v --remove-orphans prune: docker system prune -af --volumes # 資料庫備份 (使用 pg_dump) backup-db: @mkdir -p $(BACKUP_DIR) # 確保備份目錄存在 @echo "✨ 正在備份資料庫 $(DB_NAME) 到 $(BACKUP_FILE)..." @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(DB_SERVICE_NAME) \ pg_dump -U "$(DB_USER)" -d "$(DB_NAME)" > "$(BACKUP_FILE)" @echo "✅ 資料庫備份完成!" # 資料庫還原 (使用 psql) restore-db: @if [ -z "$(FILE)" ]; then echo "⚠️ 錯誤: 請提供要還原的備份檔案路徑 (例如: make restore-db FILE=./your_backup.sql)"; exit 1; fi @if [ ! -f "$(FILE)" ]; then echo "⚠️ 錯誤: 備份檔案 $(FILE) 不存在!"; exit 1; fi @echo "🚨 警告: 正在還原資料庫 $(DB_NAME)。這將清空現有資料!" @echo "請輸入 'yes' 確認繼續還原,否則請按 Ctrl+C 取消。" @read -p "確認還原? (yes/no): " CONFIRM_RESTORE; \ if [ "$$CONFIRM_RESTORE" != "yes" ]; then echo "還原已取消。"; exit 1; fi # 停止資料庫服務,確保還原過程不受干擾 @echo "⏳ 停止資料庫服務中..." @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) stop $(DB_SERVICE_NAME) # 移除舊的資料庫 Volume (確保清空資料) @echo "🗑️ 移除舊的資料庫 Volume $(DB_VOLUME_NAME)..." @docker volume rm $(DB_VOLUME_NAME) || true # 允許 volume 不存在時不報錯 # 重新啟動資料庫服務,Docker 會自動創建新的空 Volume @echo "🚀 重新啟動資料庫服務以創建新的空資料庫..." @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up -d $(DB_SERVICE_NAME) # 等待資料庫服務啟動並準備好接受連線 @echo "⏱️ 等待資料庫服務啟動並準備好..." @for i in `seq 1 10`; do \ docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(DB_SERVICE_NAME) pg_isready -d $(DB_NAME) -U $(DB_USER) > /dev/null 2>&1 && break || sleep 5; \ done @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(DB_SERVICE_NAME) pg_isready -d $(DB_NAME) -U $(DB_USER) || { echo "❌ 資料庫啟動失敗或無法連線!"; exit 1; } # 匯入備份檔案 @echo "✨ 正在將備份檔案 $(FILE) 匯入資料庫 $(DB_NAME)..." @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec -T $(DB_SERVICE_NAME) \ psql -U "$(DB_USER)" -d "$(DB_NAME)" < "$(FILE)" @echo "✅ 資料庫還原完成!"