Makefile
· 5.7 KiB · Makefile
Sin formato
# 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 "✅ 資料庫還原完成!"
| 1 | # Makefile: 適用於 docker-compose 專案,自動取用當前資料夾為專案名 |
| 2 | |
| 3 | COMPOSE := docker-compose |
| 4 | COMPOSE_FILE := docker-compose.yml |
| 5 | PROJECT_NAME := $(notdir $(CURDIR)) # 依照當前資料夾自動命名 |
| 6 | |
| 7 | # 資料庫服務名稱與 Volume 名稱 |
| 8 | DB_SERVICE_NAME := db # 在 docker-compose.yml 中定義的資料庫服務名稱 (例如:db) |
| 9 | # Docker Compose 預設會為 Volume 加上專案名稱前綴。 |
| 10 | # 所以如果你的 Volume 叫 app_postgres_data,且專案名稱是 myproject, |
| 11 | # 那實際的 Volume 名稱會是 myproject_app_postgres_data。 |
| 12 | # 若為 standalone 的 docker-compose.yml (不指定 project name),則為 app_postgres_data。 |
| 13 | DB_VOLUME_NAME := $(PROJECT_NAME)_app_postgres_data # 資料庫 Volume 的完整名稱 |
| 14 | |
| 15 | # 資料庫連線環境變數 (從 docker-compose.yml 的預設值同步過來,以確保備份還原時能正確連線) |
| 16 | DB_USER ?= postgres # 若未從環境變數指定,預設為 postgres |
| 17 | DB_NAME ?= app_db # 若未從環境變數指定,預設為 app_db |
| 18 | DB_PASSWORD ?= password # 若未從環境變數指定,預設為 password |
| 19 | |
| 20 | # 備份檔案名稱與路徑 |
| 21 | BACKUP_DIR := ./db_backups # 備份檔案存放的目錄 |
| 22 | BACKUP_FILE := $(BACKUP_DIR)/$(shell date +%Y%m%d_%H%M%S)_$(PROJECT_NAME)_db_backup.sql |
| 23 | |
| 24 | # 可選自訂 .env 變數(預設 docker-compose 自動載入 .env 檔) |
| 25 | # ENV_FILE := .env |
| 26 | |
| 27 | .PHONY: help up up-fg down build restart logs ps exec clean prune backup-db restore-db |
| 28 | |
| 29 | help: |
| 30 | @echo "🔧 Docker Compose Makefile 指令:" |
| 31 | @echo " make up - 啟動所有服務 (背景執行)" |
| 32 | @echo " make up-fg - 前景執行(方便除錯)" |
| 33 | @echo " make down - 停止並移除服務容器" |
| 34 | @echo " make build - 重新建構服務映像檔" |
| 35 | @echo " make restart - 重啟所有服務" |
| 36 | @echo " make logs - 查看服務日誌" |
| 37 | @echo " make ps - 顯示服務狀態" |
| 38 | @echo " make exec SERVICE - 進入指定服務容器的 shell (預設:db)" |
| 39 | @echo " make clean - 清理所有服務容器與相關 Volume (適合砍掉重練)" |
| 40 | @echo " make prune - 清除未使用的 Docker 資源 (映像檔、網路、Volume)" |
| 41 | @echo "" |
| 42 | @echo " make backup-db - 備份 PostgreSQL 資料庫到 ./db_backups/" |
| 43 | @echo " make restore-db FILE - 還原 PostgreSQL 資料庫,FILE 是備份檔的完整路徑" |
| 44 | @echo " 範例: make restore-db FILE=./db_backups/20250624_011228_yourproject_db_backup.sql" |
| 45 | @echo "" |
| 46 | @echo "⚠️ 注意:'restore-db' 會清空目標資料庫後再還原,請謹慎使用。" |
| 47 | |
| 48 | up: |
| 49 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up -d |
| 50 | |
| 51 | up-fg: |
| 52 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up |
| 53 | |
| 54 | down: |
| 55 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) down |
| 56 | |
| 57 | build: |
| 58 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) build |
| 59 | |
| 60 | restart: |
| 61 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) down |
| 62 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up -d |
| 63 | |
| 64 | logs: |
| 65 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) logs -f --tail=100 |
| 66 | |
| 67 | ps: |
| 68 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) ps |
| 69 | |
| 70 | # 預設進入 db 服務的 shell,也可以指定其他服務 |
| 71 | exec: |
| 72 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(or $(SERVICE),$(DB_SERVICE_NAME)) bash |
| 73 | |
| 74 | clean: |
| 75 | $(COMPOSE) -p $(PROJECT_NAME) -f $(COMPOSE_FILE) down -v --remove-orphans |
| 76 | |
| 77 | prune: |
| 78 | docker system prune -af --volumes |
| 79 | |
| 80 | # 資料庫備份 (使用 pg_dump) |
| 81 | backup-db: |
| 82 | @mkdir -p $(BACKUP_DIR) # 確保備份目錄存在 |
| 83 | @echo "✨ 正在備份資料庫 $(DB_NAME) 到 $(BACKUP_FILE)..." |
| 84 | @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(DB_SERVICE_NAME) \ |
| 85 | pg_dump -U "$(DB_USER)" -d "$(DB_NAME)" > "$(BACKUP_FILE)" |
| 86 | @echo "✅ 資料庫備份完成!" |
| 87 | |
| 88 | # 資料庫還原 (使用 psql) |
| 89 | restore-db: |
| 90 | @if [ -z "$(FILE)" ]; then echo "⚠️ 錯誤: 請提供要還原的備份檔案路徑 (例如: make restore-db FILE=./your_backup.sql)"; exit 1; fi |
| 91 | @if [ ! -f "$(FILE)" ]; then echo "⚠️ 錯誤: 備份檔案 $(FILE) 不存在!"; exit 1; fi |
| 92 | @echo "🚨 警告: 正在還原資料庫 $(DB_NAME)。這將清空現有資料!" |
| 93 | @echo "請輸入 'yes' 確認繼續還原,否則請按 Ctrl+C 取消。" |
| 94 | @read -p "確認還原? (yes/no): " CONFIRM_RESTORE; \ |
| 95 | if [ "$$CONFIRM_RESTORE" != "yes" ]; then echo "還原已取消。"; exit 1; fi |
| 96 | |
| 97 | # 停止資料庫服務,確保還原過程不受干擾 |
| 98 | @echo "⏳ 停止資料庫服務中..." |
| 99 | @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) stop $(DB_SERVICE_NAME) |
| 100 | |
| 101 | # 移除舊的資料庫 Volume (確保清空資料) |
| 102 | @echo "🗑️ 移除舊的資料庫 Volume $(DB_VOLUME_NAME)..." |
| 103 | @docker volume rm $(DB_VOLUME_NAME) || true # 允許 volume 不存在時不報錯 |
| 104 | |
| 105 | # 重新啟動資料庫服務,Docker 會自動創建新的空 Volume |
| 106 | @echo "🚀 重新啟動資料庫服務以創建新的空資料庫..." |
| 107 | @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) up -d $(DB_SERVICE_NAME) |
| 108 | |
| 109 | # 等待資料庫服務啟動並準備好接受連線 |
| 110 | @echo "⏱️ 等待資料庫服務啟動並準備好..." |
| 111 | @for i in `seq 1 10`; do \ |
| 112 | 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; \ |
| 113 | done |
| 114 | @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec $(DB_SERVICE_NAME) pg_isready -d $(DB_NAME) -U $(DB_USER) || { echo "❌ 資料庫啟動失敗或無法連線!"; exit 1; } |
| 115 | |
| 116 | # 匯入備份檔案 |
| 117 | @echo "✨ 正在將備份檔案 $(FILE) 匯入資料庫 $(DB_NAME)..." |
| 118 | @docker compose -p $(PROJECT_NAME) -f $(COMPOSE_FILE) exec -T $(DB_SERVICE_NAME) \ |
| 119 | psql -U "$(DB_USER)" -d "$(DB_NAME)" < "$(FILE)" |
| 120 | @echo "✅ 資料庫還原完成!" |
docker-compose.yml
· 2.5 KiB · YAML
Sin formato
db:
image: postgres:15 # 使用 PostgreSQL 15 版的 Docker 映像檔
container_name: app_db # 設定容器名稱,方便辨識
environment:
POSTGRES_USER: ${DB_USER:-postgres} # 資料庫使用者帳號,可由 DB_USER 環境變數指定,預設為 'postgres'
POSTGRES_DB: ${DB_NAME:-app_db} # 資料庫名稱,可由 DB_NAME 環境變數指定,預設為 'app_db'
POSTGRES_PASSWORD: ${DB_PASSWORD:-password} # 資料庫密碼,可由 DB_PASSWORD 環境變數指定,預設為 'password'
healthcheck: # 健康檢查設定,確認資料庫服務是否正常運作
test: [ "CMD-SHELL", "pg_isready -d ${DB_NAME:-app_db} -U ${DB_USER:-postgres}" ] # 檢查資料庫是否可連線,使用預設或指定的資料庫/使用者
interval: 10s # 每 10 秒檢查一次
timeout: 5s # 每次檢查的逾時時間
retries: 5 # 失敗重試次數
restart: unless-stopped # 容器停止後自動重啟,除非手動停止
networks:
- app_network # 將此容器加入 app_network 網路,方便與其他服務溝通
volumes:
- app_postgres_data:/var/lib/postgresql/data # 將資料庫數據持久化到 Docker Volume,避免容器移除後資料遺失
- type: bind # 使用 bind mount 方式掛載
source: ./database_init # 掛載本機端 ./database_init 資料夾 (請確保你的初始化腳本放在此處)
target: /docker-entrypoint-initdb.d # 掛載到容器內 PostgreSQL 啟動時會自動執行 SQL/Shell 腳本的目錄
consistency: cached # 快取一致性模式,提升效能
command: > # 容器啟動時執行的命令,用於處理初始化腳本的換行符號及權限
bash -c ' if command -v apt-get >/dev/null 2>&1; then # 檢查是否為 Debian/Ubuntu 系列系統
apt-get update && apt-get install -y dos2unix # 安裝 dos2unix 工具
elif command -v apk >/dev/null 2>&1; then # 檢查是否為 Alpine 系列系統
apk add --no-cache dos2unix # 安裝 dos2unix 工具
fi && find /docker-entrypoint-initdb.d -type f -name "*.sh" -exec sh -c '\'' # 尋找初始化目錄下的 .sh 腳本
dos2unix "{}" 2>/dev/null || true # 轉換 Windows 換行符號為 Unix 格式 (忽略錯誤)
chmod +x "{}" # 賦予腳本執行權限
'\'' \; && exec docker-entrypoint.sh postgres ' # 執行 PostgreSQL 官方的入口點腳本
volumes:
app_postgres_data: # 定義一個名為 app_postgres_data 的 Docker Volume,用來儲存 PostgreSQL 資料
networks:
app_network: # 定義一個名為 app_network 的 Docker 網路,用於服務間的內部通訊
| 1 | db: |
| 2 | image: postgres:15 # 使用 PostgreSQL 15 版的 Docker 映像檔 |
| 3 | container_name: app_db # 設定容器名稱,方便辨識 |
| 4 | environment: |
| 5 | POSTGRES_USER: ${DB_USER:-postgres} # 資料庫使用者帳號,可由 DB_USER 環境變數指定,預設為 'postgres' |
| 6 | POSTGRES_DB: ${DB_NAME:-app_db} # 資料庫名稱,可由 DB_NAME 環境變數指定,預設為 'app_db' |
| 7 | POSTGRES_PASSWORD: ${DB_PASSWORD:-password} # 資料庫密碼,可由 DB_PASSWORD 環境變數指定,預設為 'password' |
| 8 | healthcheck: # 健康檢查設定,確認資料庫服務是否正常運作 |
| 9 | test: [ "CMD-SHELL", "pg_isready -d ${DB_NAME:-app_db} -U ${DB_USER:-postgres}" ] # 檢查資料庫是否可連線,使用預設或指定的資料庫/使用者 |
| 10 | interval: 10s # 每 10 秒檢查一次 |
| 11 | timeout: 5s # 每次檢查的逾時時間 |
| 12 | retries: 5 # 失敗重試次數 |
| 13 | restart: unless-stopped # 容器停止後自動重啟,除非手動停止 |
| 14 | networks: |
| 15 | - app_network # 將此容器加入 app_network 網路,方便與其他服務溝通 |
| 16 | volumes: |
| 17 | - app_postgres_data:/var/lib/postgresql/data # 將資料庫數據持久化到 Docker Volume,避免容器移除後資料遺失 |
| 18 | - type: bind # 使用 bind mount 方式掛載 |
| 19 | source: ./database_init # 掛載本機端 ./database_init 資料夾 (請確保你的初始化腳本放在此處) |
| 20 | target: /docker-entrypoint-initdb.d # 掛載到容器內 PostgreSQL 啟動時會自動執行 SQL/Shell 腳本的目錄 |
| 21 | consistency: cached # 快取一致性模式,提升效能 |
| 22 | command: > # 容器啟動時執行的命令,用於處理初始化腳本的換行符號及權限 |
| 23 | bash -c ' if command -v apt-get >/dev/null 2>&1; then # 檢查是否為 Debian/Ubuntu 系列系統 |
| 24 | apt-get update && apt-get install -y dos2unix # 安裝 dos2unix 工具 |
| 25 | elif command -v apk >/dev/null 2>&1; then # 檢查是否為 Alpine 系列系統 |
| 26 | apk add --no-cache dos2unix # 安裝 dos2unix 工具 |
| 27 | fi && find /docker-entrypoint-initdb.d -type f -name "*.sh" -exec sh -c '\'' # 尋找初始化目錄下的 .sh 腳本 |
| 28 | dos2unix "{}" 2>/dev/null || true # 轉換 Windows 換行符號為 Unix 格式 (忽略錯誤) |
| 29 | chmod +x "{}" # 賦予腳本執行權限 |
| 30 | '\'' \; && exec docker-entrypoint.sh postgres ' # 執行 PostgreSQL 官方的入口點腳本 |
| 31 | |
| 32 | volumes: |
| 33 | app_postgres_data: # 定義一個名為 app_postgres_data 的 Docker Volume,用來儲存 PostgreSQL 資料 |
| 34 | |
| 35 | networks: |
| 36 | app_network: # 定義一個名為 app_network 的 Docker 網路,用於服務間的內部通訊 |