使用 docker 進行資料庫主從配置,因為我有這個需求,而在網上搜尋後發現沒有滿足我需求的相關實踐文件,有的是一些零零碎碎的文件,而且在參照這些文件進行部署的時候我還踩了許多坑。
因此根據我自己部署成功的經驗,我寫了這個文件。
使用 docker 自然就需要有 docker 環境,當然 docker 的映象在國內訪問比較慢,建議使用國內的源。
構建 DockerFile
我們的工作是在 Mysql 映象基礎上進行的。
docker pull mysql:5.7.20
這條命令會下載最新的 mysql 映象,當然也可以指定版本。
新建一個 DockerFile 檔案:
FROM mysql:5.7.20
EXPOSE 3306
COPY my.cnf /etc/mysql/
CMD ["mysqld"]複製程式碼
在構建映象前,我們需要 mysql 的配置檔案 my.cnf ,可以先啟動一個 mysql 的容器,然後進入容器複製它下來,並對其進行修改:
!includedir /etc/mysql/conf.d/
[mysqld]
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
datadir=/var/lib/mysql
#log-error=/var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
log-bin=/var/log/mysql/mysql-bin.index
server-id=1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0複製程式碼
以上是我修改好的一個 my.conf 檔案,我們主要修改的是以下這些選項:
#bind-address = 127.0.0.1 # 註釋這個選項可以讓遠端機器訪問,或者可以修改為 0.0.0.0
log-bin=/var/log/mysql/mysql-bin.index # 開啟 log-bin 日誌,日誌路徑
server-id=1 # 伺服器唯一ID,預設是1,一般取IP最後一段,這裡看情況分配複製程式碼
這是我的主庫的 my.cnf
,從庫的基本一樣,只是 servier-id
不一樣,從庫為 2,將這個檔案也放在資料夾裡。
構建需要的檔案結構就是以下這樣:
master
├── Dockerfile
└── my.cnf
slave
├── Dockerfile
└── my.cnf複製程式碼
然後在master目錄中使用 docker build -t master/mysql:5.7.20 .
命令構建映象主庫,從庫構建命令 docker build -t slave/mysql:5.7.20 .
。命令最後有個.
,不要忘記,代表當前目錄。-t 的意思是tag,是 --tag 的縮寫,也就是命名這個映象,如果不加docker會隨機給這個映象一個名字,建議格式為name:tag
配置docker容器
構建完成後我們使用以下命令啟動主庫和從庫:
docker run -p 3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=root -d master/mysql:5.7.20
docker run -p 3306 --name mysql-slave --link mysql-master:master -e MYSQL_ROOT_PASSWORD=root -d slave/mysql:5.7.20複製程式碼
然後分別執行docker exec -it mysql-master bash
和docker exec -it slave-master bash
命令進入到容器內部。執行mysql -uroot -proot
進入mysql環境,這時我們的環境搭建就已經完成了,下面正式配置主從連線。
當然此時docker會分配一個唯一的埠給容器,我們也可以用mysql客戶端連線進行配置。使用docker ps
檢視埠號,就可以用客戶端連線進行管理。
☁ mysql-master-slave docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c7648e829e0 slave/mysql:5.7.20 "docker-entrypoint..." 4 minutes ago Up 4 minutes 0.0.0.0:32769->3306/tcp mysql-slave
483842c63235 master/mysql:5.7.20 "docker-entrypoint..." 5 minutes ago Up 5 minutes 0.0.0.0:32768->3306/tcp mysql-master複製程式碼
使用GRANT REPLICATION SLAVE ON *.* to 'user'@'%' identified by 'mysql';
或者 GRANT REPLICATION SLAVE ON *.* TO 'user'@'192.168.1.200' IDENTIFIED BY 'mysql';
建立一個使用者,上一個是所有ip都可以訪問,下一個是指定ip才可以訪問。
然後使用GRANT SELECT,REPLICATION SLAVE ON *.* TO 'user'@'%';
給這個使用者讀取許可權。
使用show master status
檢視mysql主容器的狀態,列印如下資訊:
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+複製程式碼
使用hostname
檢視主容器的hostname,如我的主容器是483842c63235
。
接下來配置從庫mysql:
change master to
master_host='master',#要連線的主伺服器的ip
master_user='user',#指定的使用者名稱,最好不要用root
master_log_file='mysql-bin.000003',#主庫記錄的值
master_log_pos=154,#主庫的pos值
master_port=3306,#主庫3306對映的埠
master_password='mysql';#主庫要連線的使用者的密碼了複製程式碼
使用start slave
啟動主從同步
使用命令檢視show slave status\G
列印如下資訊:
*************************** 1. row ***************************
Slave_IO_State: Connecting to master
Master_Host: master //主伺服器地址
Master_User: user //授權帳戶名,儘量避免使用root
Master_Port: 3306 //資料庫埠,部分版本沒有此行
Connect_Retry: 60
Master_Log_File: mysql-bin.000003 //同步主庫的日誌檔名
Read_Master_Log_Pos: 154 //同步讀取二進位制日誌的位置,大於等於
Relay_Log_File: 6c7648e829e0-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes //此狀態必須YES
Slave_SQL_Running: Yes //此狀態必須YES
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 154
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
Master_UUID:
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)複製程式碼
這樣就是完成了一組主從mysql的配置。
shell指令碼
一下一個相應的shell指令碼,可以在1分鐘能啟動一組mysql主從容器,執行這個指令碼需要稍作修改,主要是mysql配置檔案。
#!/bin/bash
MASTER_DIR=/var/lib/mysql/mysql-master
SLAVE_DIR=/var/lib/mysql/mysql-slave
## First we could rm the existed container
docker rm -f mysql-master
docker rm -f mysql-slave
## Rm the existed directory
rm -rf $MASTER_DIR
rm -rf $SLAVE_DIR
## Start instance
docker run -p 3306 --name mysql-master -v /etc/master.cnf:/etc/mysql/my.cnf -v $MASTER_DIR:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d master/mysql:5.7.20
docker run -p 3306 --name mysql-slave -v /etc/slave.cnf:/etc/mysql/my.cnf -v $MASTER_DIR:/var/lib/mysql --link mysql-master:master -e MYSQL_ROOT_PASSWORD=root -d slave/mysql:5.7.20
## Creating a User for Replication
docker stop mysql-master mysql-slave
docker start mysql-master mysql-slave
sleep 3
docker exec -it mysql-master mysql -S /var/lib/mysql/mysql.sock -e "CREATE USER 'users'@'127.0.0.1' IDENTIFIED BY 'mysql';GRANT REPLICATION SLAVE ON *.* TO 'users'@'127.0.0.1';"
## Obtaining the Replication Master Binary Log Coordinates
master_status=`docker exec -it master mysql -S /var/lib/mysql/mysql.sock -e "show master status\G"`
master_log_file=`echo "$master_status" | awk 'NR==2{print substr($2,1,length($2)-1)}'`
master_log_pos=`echo "$master_status" | awk 'NR==3{print $2}'`
master_log_file="'""$master_log_file""'"
## Setting Up Replication Slaves
docker exec -it mysql-slave mysql -S /var/lib/mysql/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='master',MASTER_PORT=3306,MASTER_USER='users',MASTER_PASSWORD='mysql',MASTER_LOG_FILE=$master_log_file,MASTER_LOG_POS=$master_log_pos;"
docker exec -it mysql-slave mysql -S /var/lib/mysql/mysql.sock -e "start slave;"
docker exec -it mysql-slave mysql -S /var/lib/mysql/mysql.sock -e "show slave status\G"
## Creates shortcuts
grep "alias mysql-master" /etc/profile
if [ $? -eq 1 ];then
echo 'alias mysql="docker exec -it mysql-master mysql"' >> /etc/profile
echo 'alias master="docker exec -it mysql-master mysql -h 127.0.0.1 -P3306"' >> /etc/profile
echo 'alias slave="docker exec -it mysql-master mysql -h 127.0.0.1 -P3307"' >> /etc/profile
source /etc/profile
fi複製程式碼