Docker Compose를 사용하여 로컬 환경이나 서버에서 여러 개의 MySQL 인스턴스를 실행하고, 마스터-슬레이브(Primary-Replica) 복제 환경을 구축하는 과정을 단계별로 설명합니다. 이 가이드에서는 MySQL 8.0 이미지를 사용하며, 호스트 포트와 볼륨 경로를 재구성하여 충돌을 방지하고 네트워크 설정을 최적화합니다.
1. 초기 Docker Compose 파일 작성 및 컨테이너 실행
먼저 설정 파일 디렉토리 매핑 없이 기본 컨테이너를 실행하여 초기 데이터 디렉토리와 설정 파일을 생성합니다. docker-compose.yml 파일을 다음과 같이 작성합니다.
version: '3.8'
services:
mysql-primary:
image: mysql:8.0
container_name: mysql-primary
restart: unless-stopped
ports:
- "3310:3306"
environment:
MYSQL_ROOT_PASSWORD: "SecurePass!2024"
TZ: "Asia/Seoul"
volumes:
- /data/mysql/primary/data:/var/lib/mysql
- /data/mysql/primary/init:/docker-entrypoint-initdb.d
mysql-replica:
image: mysql:8.0
container_name: mysql-replica
restart: unless-stopped
ports:
- "3311:3306"
environment:
MYSQL_ROOT_PASSWORD: "SecurePass!2024"
TZ: "Asia/Seoul"
volumes:
- /data/mysql/replica/data:/var/lib/mysql
- /data/mysql/replica/init:/docker-entrypoint-initdb.d
컨테이너를 백그라운드에서 실행합니다.
docker-compose up -d
2. 호스트로 설정 파일 추출 및 볼륨 매핑 업데이트
실행 중인 컨테이너 내부의 기본 MySQL 설정 파일을 호스트 디렉토리로 복사합니다.
mkdir -p /data/mysql/primary/conf /data/mysql/replica/conf
docker cp mysql-primary:/etc/mysql/conf.d /data/mysql/primary/conf/
docker cp mysql-replica:/etc/mysql/conf.d /data/mysql/replica/conf/
복사가 완료되면 docker-compose.yml 파일을 수정하여 설정 디렉토리를 마운트합니다.
version: '3.8'
services:
mysql-primary:
image: mysql:8.0
container_name: mysql-primary
restart: unless-stopped
ports:
- "3310:3306"
environment:
MYSQL_ROOT_PASSWORD: "SecurePass!2024"
TZ: "Asia/Seoul"
volumes:
- /data/mysql/primary/data:/var/lib/mysql
- /data/mysql/primary/conf/conf.d:/etc/mysql/conf.d
- /data/mysql/primary/init:/docker-entrypoint-initdb.d
mysql-replica:
image: mysql:8.0
container_name: mysql-replica
restart: unless-stopped
ports:
- "3311:3306"
environment:
MYSQL_ROOT_PASSWORD: "SecurePass!2024"
TZ: "Asia/Seoul"
volumes:
- /data/mysql/replica/data:/var/lib/mysql
- /data/mysql/replica/conf/conf.d:/etc/mysql/conf.d
- /data/mysql/replica/init:/docker-entrypoint-initdb.d
변경 사항을 적용하기 위해 컨테이너를 재시작합니다.
docker-compose down
docker-compose up -d
3. 마스터(Primary) 서버 설정
호스트의 /data/mysql/primary/conf/conf.d/my.cnf 파일을 열어 바이너리 로깅과 서버 ID를 설정합니다.
[mysqld]
server-id=100
log-bin=mysql-bin
binlog-format=ROW
read-only=0
# 복제에서 제외할 데이터베이스 (선택 사항)
# binlog-ignore-db=sys
# binlog-ignore-db=information_schema
# 복제할 특정 데이터베이스 지정 (선택 사항)
binlog-do-db=app_production
binlog-do-db=app_analytics
4. 슬레이브(Replica) 서버 설정
호스트의 /data/mysql/replica/conf/conf.d/my.cnf 파일을 수정합니다.
[mysqld]
server-id=200
log-bin=mysql-bin
relay-log=relay-bin
read-only=1
super-read-only=1
설정 파일 수정 후 두 컨테이너를 재시작하여 구성을 로드합니다.
docker-compose restart
5. 마스터 서버에서 복제 사용자 생성
마스터 컨테이너에 접속하여 복제 전용 사용자를 생성하고 권한을 부여합니다. MySQL 8.0부터는 GRANT 문으로 사용자를 동시에 생성할 수 없으므로 분리하여 실행해야 합니다.
docker exec -it mysql-primary mysql -uroot -p"SecurePass!2024"
MySQL 프롬프트에서 다음 쿼리를 실행합니다.
CREATE USER 'repl_user'@'%' IDENTIFIED WITH mysql_native_password BY 'ReplPass#99';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
현재 바이너리 로그 파일 이름과 위치(Position)를 확인합니다.
SHOW MASTER STATUS;
결과에서 File과 Position 값을 기록해 둡니다. (예: mysql-bin.000001, 156)
6. 슬레이브 서버에서 복제 구성 및 시작
슬레이브 컨테이너에 접속합니다.
docker exec -it mysql-replica mysql -uroot -p"SecurePass!2024"
마스터 서버 정보를 입력하고 복제를 시작합니다. 앞서 확인한 로그 파일과 위치 값을 사용해야 합니다.
CHANGE MASTER TO
MASTER_HOST='mysql-primary',
MASTER_USER='repl_user',
MASTER_PASSWORD='ReplPass#99',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=156,
GET_MASTER_PUBLIC_KEY=1;
START SLAVE;
참고: Docker Compose 네트워크 내부이므로 MASTER_HOST에 마스터 컨테이너 이름(mysql-primary)을 직접 사용할 수 있습니다.
7. 복제 상태 확인
슬레이브 서버에서 복제가 정상적으로 작동하는지 확인합니다.
SHOW SLAVE STATUS\G
출력 결과에서 다음 두 항목이 모두 Yes로 표시되면 복제가 성공적으로 구성된 것입니다.
Slave_IO_Running: YesSlave_SQL_Running: Yes
중요: 복제를 시작하기 전, 마스터와 슬레이브 간에 데이터 일관성을 맞추기 위해 대상 데이터베이스(위 예시의 app_production 등)를 양쪽 인스턴스에 미리 수동으로 생성해 두어야 합니다.