Requirement:
- 1 Database – Master server (prefer Linux Ubuntu, VM or Onprem), Docker compose pre-installed.
- 1 Database – Slave/Replica (prefer Linux Ubuntu, VM or Onprem), Docker compose pre-installed.
- Network connection between Master-Slave with internet connection for pull MySQL image.
- Storage space, IOPS, and others refer to your requirement and need.
Directory structure
.
├── docker-compose.yml
├── init.sql
├── master_data
│ ├── digikam
│ ├── mysql
│ ├── performance_schema
│ └── sys
├── mysql_config
│ └── my.cnf
└── mysql_logs
without further ado let’s start.
ssh to Master server and add docker-compose.yml, init.sql to your preferred root folder then create “mysql_config” folder and save my.cnf there “./mysql_config/my.cnf”
# Docker-compose.yml
# Server Master
services:
mysql-master:
#for MySQL Community edition: mysql:8.0
#for MySQL Enterprise edition: container-registry.oracle.com/mysql/enterprise-server:8.0
image: container-registry.oracle.com/mysql/enterprise-server:8.0
container_name: mysql-master
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: MFfj3iXZ1e2F3amqbiFX # Replace with your own password
ports:
- "3306:3306"
volumes:
- ./master_data:/var/lib/mysql #expose data to host
- ./mysql_logs:/var/log #expose log to host
- ./mysql_config/my.cnf:/etc/my.cnf #expose config to host
- /usr/share/zoneinfo:/usr/share/zoneinfo:ro
- ./init.sql:/docker-entrypoint-initdb.d/init.sql #exec pre-setup config
command: --server-id=1 --gtid-mode=ON --enforce-gtid-consistency=ON --max_allowed_packet=128M
logging:
driver: "json-file"
options:
max-size: "10m" # Max log size per file
max-file: "5" # max log file to keep
# init.sql
-- Check DB if not exsist then create
CREATE DATABASE IF NOT EXISTS digikam;
-- Create replication user
CREATE USER IF NOT EXISTS 'ReplicationUser'@'%' IDENTIFIED WITH caching_sha2_password BY 'ReplicationPassword';
GRANT REPLICATION SLAVE ON *.* TO 'ReplicationUser'@'%';
-- We not set root account to allow remotely, se we need new for easy setup
CREATE USER IF NOT EXISTS 'YourAdminName'@'%' IDENTIFIED WITH caching_sha2_password BY 'X1GYZjc8aT6TY8ZP1qwA';
GRANT ALL PRIVILEGES ON *.* TO 'YourAdminName'@'%' WITH GRANT OPTION;
-- Sample, Create user for digikam
CREATE USER IF NOT EXISTS 'digikam'@'%' IDENTIFIED WITH mysql_native_password BY 'nLqTf0QeEbZcf103Mzic';
GRANT ALL PRIVILEGES ON *.* TO 'digikam'@'%' WITH GRANT OPTION;
-- Apply perubahan
FLUSH PRIVILEGES;
#./mysql_config/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html
[mysqld]
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
server-id=1
log_bin=mysql-bin
gtid_mode=ON
enforce_gtid_consistency=ON
innodb_redo_log_capacity = 10G
with evening is setup, lets running docker compose
# sudo docker-compose up -d && sudo docker-compose logs -f
when everting is work you will ending with this log (ctrl+c to stop/exit log tail)
...
mysql-master | [Entrypoint] MySQL init process done. Ready for start up.
mysql-master |
mysql-master | [Entrypoint] Starting MySQL 8.0.45-1.2.24-server
mysql-master | 2026-06-05T13:09:50.269447Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.45-commercial) starting as process 1
mysql-master | 2026-06-05T13:09:50.275298Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
mysql-master | 2026-06-05T13:09:50.478426Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
mysql-master | 2026-06-05T13:09:50.630577Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
mysql-master | 2026-06-05T13:09:50.630604Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
mysql-master | 2026-06-05T13:09:50.656198Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
mysql-master | 2026-06-05T13:09:50.656269Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.45-commercial' socket: '/var/lib/mysql/mysql.sock' port: 3306 MySQL Enterprise Server - Commercial.
mysql-master | 2026-06-05T13:11:21.956407Z 21 [Warning] [MY-013360] [Server] Plugin mysql_native_password reported: ''mysql_native_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'
Next we will gonna create Slave or replica, with directory structure is same like master.
# docker-compose.yml
# Server Replica
services:
mysql-slave1:
#for MySQL Community edition: mysql:8.0
#for MySQL Enterprise edition: container-registry.oracle.com/mysql/enterprise-server:8.0
image: container-registry.oracle.com/mysql/enterprise-server:8.0
container_name: mysql-slave1
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: MFfj3iXZ1e2F3amqbiFX # Replace with your own password
ports:
- "3306:3306"
volumes:
- ./slave1_data:/var/lib/mysql
- ./mysql_logs:/var/log # expose log to host
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
command: --server-id=2 --gtid-mode=ON --enforce-gtid-consistency=ON --max_allowed_packet=128M --relay-log=relay-bin --read-only=1
logging:
driver: "json-file"
options:
max-size: "10m" # Max log size per file
max-file: "5" # max log file to keep
init.sql file
# init.sql
-- Check DB if not exsist then create
CREATE DATABASE IF NOT EXISTS digikam;
-- Create replication user
CREATE USER IF NOT EXISTS 'ReplicationUser'@'%' IDENTIFIED WITH caching_sha2_password BY 'ReplicationPassword';
GRANT REPLICATION SLAVE ON *.* TO 'ReplicationUser'@'%';
-- We not set root account to allow remotely, se we need new for easy setup
CREATE USER IF NOT EXISTS 'YourAdminName'@'%' IDENTIFIED WITH caching_sha2_password BY 'X1GYZjc8aT6TY8ZP1qwA';
GRANT ALL PRIVILEGES ON *.* TO 'YourAdminName'@'%' WITH GRANT OPTION;
-- Sample, Create user for digikam
CREATE USER IF NOT EXISTS 'digikam'@'%' IDENTIFIED WITH mysql_native_password BY 'nLqTf0QeEbZcf103Mzic';
GRANT ALL PRIVILEGES ON *.* TO 'digikam'@'%' WITH GRANT OPTION;
-- Apply perubahan
FLUSH PRIVILEGES;
CHANGE MASTER TO
MASTER_HOST='192.168.0.10', # DNS or IP's
MASTER_USER='ReplicationUser',
MASTER_PASSWORD='ReplicationPassword',
MASTER_SSL=1,
MASTER_AUTO_POSITION=1;
START SLAVE;
#./mysql_config/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
SET GLOBAL host_cache_size=0;
SET GLOBAL log_bin_trust_function_creators=1;
innodb_redo_log_capacity = 10G
log-bin=/var/lib/mysql/binlog
# sudo docker-compose up -d && sudo docker-compose logs -f
when everting is work you will ending with this log (ctrl+c to stop/exit log tail)
✔ Network root_default Created 0.0s
✔ Container mysql-slave1 Created 0.0s
mysql-slave1 | [Entrypoint] MySQL Docker Image 8.0.46-1.2.25-server
mysql-slave1 | [Entrypoint] Starting MySQL 8.0.46-1.2.25-server
mysql-slave1 | 2026-06-06T17:10:28.809871Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
mysql-slave1 | 2026-06-06T17:10:28.811132Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.46-commercial) starting as process 1
mysql-slave1 | 2026-06-06T17:10:28.816139Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
mysql-slave1 | 2026-06-06T17:10:28.947828Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
mysql-slave1 | 2026-06-06T17:10:29.152463Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
mysql-slave1 | 2026-06-06T17:10:29.152498Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
mysql-slave1 | 2026-06-06T17:10:29.247452Z 5 [Warning] [MY-010897] [ReplicationUser] Storing MySQL user name or password information in the connection metadata repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START REPLICA; see the 'START REPLICA Syntax' in the MySQL Manual for more information.
mysql-slave1 | 2026-06-06T17:10:29.249598Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.46-commercial' socket: '/var/lib/mysql/mysql.sock' port: 3306 MySQL Enterprise Server - Commercial.
mysql-slave1 | 2026-06-06T17:10:29.249637Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
mysql-slave1 | 2026-06-06T17:10:29.260492Z 5 [System] [MY-014002] [ReplicationUser] Replica receiver thread for channel '': connected to source '[email protected]:3306' with server_uuid=d18283e1-60df-11f1-bb05-46b3d3e6c20c, server_id=1. Starting GTID-based replication.
