Docker 實戰:MySQL 8 全自動 GTID 主從複製架構指南
在傳統部署中,設定 MySQL 複製最煩瑣的就是「手動記錄位點(Log Position)」以及「手動執行 CHANGE MASTER TO」。透過 Docker 與 GTID(全域事務 ID),我們可以實現**「一行指令,環境即建好」**的目標。
1. 專案目錄結構
我們需要明確的分層結構,確保設定檔與初始化腳本能被正確掛載。
mysql-replication/
├── source/
│ ├── my.cnf # Source 設定檔
│ └── init.sql # 自動建立複製帳號
├── replica/
│ ├── my.cnf # Replica 設定檔
│ └── setup.sh # 自動化同步腳本 (關鍵!)
└── docker-compose.yml # 編排中心
2. 設定檔詳解:確保 GTID 啟用
Source 端 (source/my.cnf)
[mysqld]
server-id=1
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
# 解決 MySQL 8 認證問題
default-authentication-plugin=mysql_native_password
# 權限修正:確保 MySQL 讀取此檔不報錯
skip-host-cache
skip-name-resolve
Replica 端 (replica/my.cnf)
[mysqld]
server-id=2
relay-log=relay-bin
read_only=1
gtid_mode=ON
enforce_gtid_consistency=ON
default-authentication-plugin=mysql_native_password
3. 自動化腳本:解決「權限」與「手動操作」
A. 建立複製帳號 (source/init.sql)
此檔案放在 Source 端,容器啟動時會自動執行。
-- 建立測試資料庫
CREATE DATABASE IF NOT EXISTS app_db;
-- 建立複製專用帳號,使用 native 插件避免連線失敗
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpass';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
B. 自動化握手腳本 (replica/setup.sh)
這是最關鍵的一步。我們利用 Replica 啟動時自動執行腳本,去向 Source 請求同步。
#!/bin/bash
echo "等待 Source MySQL 啟動並就緒..."
# 確保 Source 可以連通才開始執行
until mysql -h mysql-source -urepl -preplpass -e "SELECT 1;" &> /dev/null; do
sleep 2
done
echo "開始配置 GTID 主從同步..."
mysql -uroot -prootpassword <<EOSQL
STOP REPLICA;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='mysql-source',
SOURCE_USER='repl',
SOURCE_PASSWORD='replpass',
SOURCE_AUTO_POSITION=1;
START REPLICA;
EOSQL
echo "主從同步配置完成!"
4. 編排中心:docker-compose.yml
我們加入 Healthcheck 確保啟動順序正確,並解決掛載權限問題。
services:
mysql-source:
image: mysql:8.0
container_name: mysql-source
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- ./source/my.cnf:/etc/mysql/conf.d/my.cnf
- ./source/init.sql:/docker-entrypoint-initdb.d/init.sql
- source_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-uroot", "-prootpassword"]
interval: 5s
timeout: 5s
retries: 10
mysql-replica:
image: mysql:8.0
container_name: mysql-replica
restart: always
depends_on:
mysql-source:
condition: service_healthy
environment:
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- ./replica/my.cnf:/etc/mysql/conf.d/my.cnf
- ./replica/setup.sh:/docker-entrypoint-initdb.d/setup.sh
- replica_data:/var/lib/mysql
volumes:
source_data:
replica_data:
5. 部署與權限修正
在執行啟動命令前,請務必在宿主機處理設定檔權限(這是 MySQL 容器最常見的 Permission Denied 原因):
# 修改設定檔權限,MySQL 要求不能是 777
chmod 644 ./source/my.cnf ./replica/my.cnf
# 確保 setup.sh 具備執行權限
chmod +x ./replica/setup.sh
# 一鍵啟動
docker compose up -d
6. 驗證與排錯
如何確認同步成功?
不需要進容器,直接執行:
docker exec -it mysql-replica mysql -uroot -prootpassword -e "SHOW REPLICA STATUS\G"
看這兩個 Yes 就對了:
Replica_IO_Running: YesReplica_SQL_Running: Yes
常見權限與錯誤排查
認證錯誤 (Access Denied): 檢查
source/init.sql是否確實建立了repl@'%'。設定檔被忽略: 如果日誌顯示
World-writable config file is ignored,表示你的my.cnf權限太開(需為 644)。連線被拒: 檢查
docker-compose中的服務名稱是否為mysql-source,Replica 是透過這個名稱找 Source 的。
總結
這套方案解決了你擔心的「手動操作」與「權限問題」:
檔案權限: 透過宿主機
chmod 644與 Named Volumes 解決。手動設定: 透過
replica/setup.sh自動完成CHANGE REPLICATION SOURCE。一致性: 採用 GTID,即使容器重啟或位點變動,系統也能自動找回同步點。
沒有留言:
張貼留言