Khắc phục lỗi đồng bộ MySQL Master-Slave khi IP container Docker thay đổi

Vấn đề thường gặp khi triển khai MySQL Master-Slave trong Docker là IP của container có thể thay đổi sau mỗi lần khởi động lại, dẫn đến lỗi đồng bộ (Slave không tìm thấy Master).

Giải pháp: Sử dụng mạng tùy chỉnh (custom network) và kết nối qua tên container thay vì địa chỉ IP. Docker sẽ tự động phân giải tên container thành IP trong cùng một mạng, giúp cấu hình ổn định hơn.

Các bước thực hiện

  1. Tạo mạng Docker
docker network create mysql_network
  1. Khởi tạo container Master
docker run -d \
  -p 3306:3306 \
  --network mysql_network \
  -v /home/user/mysql/master/conf:/etc/mysql/conf.d \
  -v /home/user/mysql/master/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=your_password \
  --name mysql-master \
  mysql:8.0.29

Tạo file cấu hình my.cnf tại thư mục /home/user/mysql/master/conf/:

[mysqld]
server-id=1
binlog_format=STATEMENT
# log-bin=binlog

Khởi động lại container Master:

docker restart mysql-master

Vào container và cấu hình MySQL:

docker exec -it mysql-master env LANG=C.UTF-8 /bin/bash
mysql -uroot -p
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';

Tạo user cho Slave:

CREATE USER 'slave_user'@'%';
ALTER USER 'slave_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%';
FLUSH PRIVILEGES;

Xem thông tin trạng thái Master (lưu lại FilePosition):

SHOW MASTER STATUS\G
  1. Khởi tạo container Slave
docker run -d \
  -p 3307:3306 \
  --network mysql_network \
  -v /home/user/mysql/slave1/conf:/etc/mysql/conf.d \
  -v /home/user/mysql/slave1/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=your_password \
  --name mysql-slave1 \
  mysql:8.0.29

Tạo file my.cnf cho Slave:

[mysqld]
server-id=2

Khởi động lại container Slave:

docker restart mysql-slave1

Vào container và cấu hình MySQL:

docker exec -it mysql-slave1 env LANG=C.UTF-8 /bin/bash
mysql -uroot -p
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';

Thiết lập kết nối Master-Slave (sử dụng tên container thay vì IP):

CHANGE MASTER TO MASTER_HOST='mysql-master',
  MASTER_USER='slave_user',
  MASTER_PASSWORD='your_password',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='binlog.000003',
  MASTER_LOG_POS=1379;

Khởi động Slave:

START SLAVE;

Kiểm tra trạng thái:

SHOW SLAVE STATUS\G

Kiểm tra đồng bộ

Trên Master, tạo database và bảng để kiểm tra:

CREATE DATABASE db_user;
USE db_user;
CREATE TABLE t_user (
  id BIGINT AUTO_INCREMENT,
  uname VARCHAR(30),
  PRIMARY KEY (id)
);
INSERT INTO t_user(uname) VALUES('zhang3');
INSERT INTO t_user(uname) VALUES(@@hostname);

Trên Slave, kiểm tra dữ liệu đã được đồng bộ.

Lưu ý về thứ tự khởi động

Nếu khởi động Slave trước Master, Slave có thể báo lỗi kết nối. Khi đó, khởi động lại Slave (sau khi Master đã chạy) sẽ giải quyết vấn đề. Khuyến nghị luôn khởi động Master trước, hoặc sử dụng Docker Compose để quản lý thứ tự container.

So sánh với cách dùng IP cố định

Cách truyền thống dùng địa chỉ IP (ví dụ MASTER_HOST='172.17.0.2') dễ bị lỗi khi container được restart và nhận IP mới. Cách dùng tên container trong cùng mạng Docker giúp cấu hình bền vững hơn.

Thẻ: mysql docker replication Docker Network container

Đăng vào ngày 28 tháng 8 lúc 09:06