Docker&K8s

CH_04_02_MySQL 구축

dding-shark 2025. 7. 28. 14:17
728x90

4.2 MySQL 구축

MySQL 컨테이너를 구축하기 위한 전체 디렉터리 구성은 다음과 같습니다.

.
├── containers
│   └── mysql
│       ├── Dockerfile
│       └── etc
│           └── mysql
│               └── conf.d
│                   └── slowlog.cnf
└── secrets
    ├── mysql_root_password
    └── mysql_user_password

 

 

 

 

 


 

 

4.2.1 MySQL 컨테이너 설정 확장하기

많은 서비스가 그렇듯, MySQL 역시 기본 설정만으로 모든 요구사항을 충족하기는 어렵습니다. Nginx가 /etc/nginx/conf.d 디렉터리에 설정 파일을 추가하여 기능을 확장하는 것처럼, MySQL 컨테이너도 유사한 방식으로 커스텀 설정을 적용할 수 있습니다.

설정 파일 위치 확인

먼저, 공식 MySQL 이미지가 설정을 어떻게 관리하는지 직접 확인해 보겠습니다. docker exec 명령어를 사용하면 실행 중인 컨테이너 내부에 들어가 파일 시스템을 탐색할 수 있습니다.

# 실행 중인 MySQL 컨테이너의 셸에 접속합니다.
# (컨테이너 이름 'backend_mysql_1'은 실제 환경에 맞게 변경하세요.)
$ docker exec -it backend_mysql_1 bash

# /etc 디렉터리로 이동하여 my.cnf 파일의 내용을 확인합니다.
bash-5.1# cd /etc
bash-5.1# cat my.cnf

my.cnf 파일은 MySQL의 핵심 설정 파일입니다. 그 내용을 살펴보면 커스텀 설정을 추가할 수 있는 중요한 단서를 찾을 수 있습니다.

# /etc/my.cnf

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.4/en/server-configuration-defaults.html

[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M

host-cache-size=0
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql

pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock

!includedir /etc/mysql/conf.d/

파일의 가장 마지막 줄에 있는 !includedir /etc/mysql/conf.d/ 지시어가 바로 핵심입니다. 이 지시어는 MySQL 서버가 시작될 때 /etc/mysql/conf.d/ 디렉터리 안에 있는 모든 .cnf 확장자 파일을 자동으로 읽어와 설정에 포함하도록 만듭니다.

커스텀 설정 파일 추가

이 원리를 이용하여, 우리는 성능 분석에 유용한 슬로 쿼리(Slow Query) 로그 설정을 추가해 보겠습니다. 프로젝트의 containers/mysql/etc/mysql/conf.d/ 경로에 slowlog.cnf 파일을 생성합니다.

containers/mysql/etc/mysql/conf.d/
└── slowlog.cnf   <- 이 파일을 추가합니다.

slowlog.cnf 파일의 내용은 다음과 같습니다.

[mysqld]
# 슬로 쿼리 로그 기능 활성화
slow_query_log = on

# 슬로 쿼리 로그 파일 경로 지정
slow_query_log_file = /var/log/mysql/mysql-slow.log

# 1초 이상 실행되는 쿼리를 슬로 쿼리로 간주
long_query_time = 1

# 인덱스를 사용하지 않는 쿼리도 로그에 기록
log_queries_not_using_indexes = on

이 설정 파일은 다음과 같은 역할을 합니다.

  • 슬로 쿼리 로그 활성화: 실행 시간이 오래 걸리는 쿼리를 추적하는 기능을 켭니다.
  • 로그 파일 지정: 슬로 쿼리가 발생했을 때 기록될 로그 파일의 위치를 지정합니다.
  • 시간 기준 설정: 1초를 초과하는 쿼리를 슬로 쿼리로 판단합니다.
  • 인덱스 미사용 쿼리 로깅: 최적화가 필요한 쿼리를 쉽게 찾을 수 있도록 인덱스를 사용하지 않는 쿼리도 기록합니다.

이제 Dockerfile에서 slowlog.cnf 파일을 컨테이너 이미지의 /etc/mysql/conf.d/ 디렉터리로 복사하도록 설정하면, 컨테이너가 시작될 때 해당 설정이 자동으로 적용됩니다. 이처럼 docker exec를 통해 컨테이너의 내부 동작을 이해하면, 보다 체계적이고 안정적으로 설정을 관리할 수 있습니다.

알겠습니다. docker exec를 통해 컨테이너 내부 설정을 직접 확인하고, 이를 바탕으로 커스텀 설정을 적용하는 과정을 상세히 포함하여 문서를 다시 작성해 드리겠습니다. 초보자도 따라 할 수 있도록 실제 실행 과정을 보여주는 것이 중요하죠.

다음은 요청하신 내용을 반영하여 전문적으로 다듬은 문서입니다.

 

 

 

 


 

 

4.2 MySQL 구축

MySQL 컨테이너를 구축하기 위한 전체 디렉터리 구성은 다음과 같습니다.

.
├── containers
│   └── mysql
│       ├── Dockerfile
│       └── etc
│           └── mysql
│               └── conf.d
│                   └── slowlog.cnf
└── secrets
    ├── mysql_root_password
    └── mysql_user_password

 

 

 

 

 


 

 

4.2.1 MySQL 컨테이너 설정 확장하기

많은 서비스가 그렇듯, MySQL 역시 기본 설정만으로 모든 요구사항을 충족하기는 어렵습니다. Nginx가 /etc/nginx/conf.d 디렉터리에 설정 파일을 추가하여 기능을 확장하는 것처럼, MySQL 컨테이너도 유사한 방식으로 커스텀 설정을 적용할 수 있습니다.

설정 파일 위치 확인

먼저, 공식 MySQL 이미지가 설정을 어떻게 관리하는지 직접 확인해 보겠습니다. docker exec 명령어를 사용하면 실행 중인 컨테이너 내부에 들어가 파일 시스템을 탐색할 수 있습니다.

# 실행 중인 MySQL 컨테이너의 셸에 접속합니다.
# (컨테이너 이름 'backend_mysql_1'은 실제 환경에 맞게 변경하세요.)
$ docker exec -it backend_mysql_1 bash

# /etc 디렉터리로 이동하여 my.cnf 파일의 내용을 확인합니다.
bash-5.1# cd /etc
bash-5.1# cat my.cnf

my.cnf 파일은 MySQL의 핵심 설정 파일입니다. 그 내용을 살펴보면 커스텀 설정을 추가할 수 있는 중요한 단서를 찾을 수 있습니다.

# /etc/my.cnf

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.4/en/server-configuration-defaults.html

[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M

host-cache-size=0
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql

pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock

!includedir /etc/mysql/conf.d/

파일의 가장 마지막 줄에 있는 !includedir /etc/mysql/conf.d/ 지시어가 바로 핵심입니다. 이 지시어는 MySQL 서버가 시작될 때 /etc/mysql/conf.d/ 디렉터리 안에 있는 모든 .cnf 확장자 파일을 자동으로 읽어와 설정에 포함하도록 만듭니다.

커스텀 설정 파일 추가

이 원리를 이용하여, 우리는 성능 분석에 유용한 슬로 쿼리(Slow Query) 로그 설정을 추가해 보겠습니다. 프로젝트의 containers/mysql/etc/mysql/conf.d/ 경로에 slowlog.cnf 파일을 생성합니다.

containers/mysql/etc/mysql/conf.d/
└── slowlog.cnf   <- 이 파일을 추가합니다.

slowlog.cnf 파일의 내용은 다음과 같습니다.

[mysqld]
# 슬로 쿼리 로그 기능 활성화
slow_query_log = on

# 슬로 쿼리 로그 파일 경로 지정
slow_query_log_file = /var/log/mysql/mysql-slow.log

# 1초 이상 실행되는 쿼리를 슬로 쿼리로 간주
long_query_time = 1

# 인덱스를 사용하지 않는 쿼리도 로그에 기록
log_queries_not_using_indexes = on

이 설정 파일은 다음과 같은 역할을 합니다.

  • 슬로 쿼리 로그 활성화: 실행 시간이 오래 걸리는 쿼리를 추적하는 기능을 켭니다.
  • 로그 파일 지정: 슬로 쿼리가 발생했을 때 기록될 로그 파일의 위치를 지정합니다.
  • 시간 기준 설정: 1초를 초과하는 쿼리를 슬로 쿼리로 판단합니다.
  • 인덱스 미사용 쿼리 로깅: 최적화가 필요한 쿼리를 쉽게 찾을 수 있도록 인덱스를 사용하지 않는 쿼리도 기록합니다.

이제 Dockerfile에서 slowlog.cnf 파일을 컨테이너 이미지의 /etc/mysql/conf.d/ 디렉터리로 복사하도록 설정하면, 컨테이너가 시작될 때 해당 설정이 자동으로 적용됩니다. 이처럼 docker exec를 통해 컨테이너의 내부 동작을 이해하면, 보다 체계적이고 안정적으로 설정을 관리할 수 있습니다.

 

 

 

 


 

 

4.2.2 MySQL Dockerfile

이제 커스텀 설정 파일(slowlog.cnf)을 MySQL 이미지에 포함시키기 위한 Dockerfile을 작성합니다.

# containers/mysql/Dockerfile

# 공식 MySQL 8.0.33 이미지를 기반으로 새로운 이미지를 생성합니다.
FROM mysql:8.0.33

# 호스트의 커스텀 설정 파일 디렉터리를 컨테이너 내부의 설정 디렉터리로 복사합니다.
COPY ./etc/mysql/conf.d /etc/mysql/conf.d

Dockerfile은 매우 간단합니다. COPY 명령어를 통해 우리가 생성한 slowlog.cnf 파일이 포함된 conf.d 디렉터리 전체를 이미지의 /etc/mysql/conf.d로 복사합니다. 이렇게 빌드된 이미지는 실행될 때 자동으로 슬로 쿼리 로그 설정을 적용하게 됩니다.

 

 

 

 


 

 

4.2.3 Docker Compose를 이용한 서비스 정의

이제 docker-compose.yaml 파일을 통해 MySQL 서비스를 최종적으로 정의합니다. 이 파일은 Dockerfile을 사용하여 이미지를 빌드하고, 데이터베이스 운영에 필요한 환경 변수, 보안 정보, 데이터 영속성 등을 체계적으로 관리합니다.

# compose.yaml

version: "3.9"
services:
  mysql:
    # 이미지 빌드 방법을 정의합니다.
    build: 
      context: ./containers/mysql # Dockerfile이 위치한 경로

    # 컨테이너 실행에 필요한 환경 변수를 설정합니다.
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
      MYSQL_DATABASE: taskapp
      MYSQL_USER: taskapp_user
      MYSQL_PASSWORD_FILE: /run/secrets/mysql_user_password

    # 외부의 민감한 정보를 안전하게 컨테이너에 전달합니다.
    secrets:
      - mysql_root_password
      - mysql_user_password

    # 데이터베이스 데이터를 영속적으로 저장하기 위해 볼륨을 마운트합니다.
    volumes:
      - mysql_data:/var/lib/mysql

    # 호스트와 컨테이너의 포트를 연결합니다.
    ports:
      - "3307:3306"

# 최상위 키에서 secrets를 정의합니다.
secrets:
  mysql_root_password:
    file: ./secrets/mysql_root_password # 호스트에 저장된 비밀번호 파일 경로
  mysql_user_password:
    file: ./secrets/mysql_user_password

# 최상위 키에서 명명된 볼륨(named volume)을 정의합니다.
volumes:
  mysql_data:

 

 

상세 설명

  • build.context: docker-compose가 이미지를 빌드할 때 사용할 Dockerfile의 위치를 지정합니다. ./containers/mysql 디렉터리로 지정하면, 해당 경로의 Dockerfile을 사용하여 mysql 서비스 이미지를 빌드합니다.
  • environment: 컨테이너 환경 변수를 설정합니다.
    • MYSQL_ROOT_PASSWORD_FILE: MYSQL_ROOT_PASSWORD와 달리, 비밀번호가 저장된 파일의 경로를 값으로 받습니다. 이는 비밀번호를 환경 변수에 직접 노출하지 않아 보안에 더 안전한 방식입니다.
    • MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD_FILE: 컨테이너가 처음 시작될 때 지정된 이름으로 데이터베이스와 사용자를 자동으로 생성합니다. 사용자 비밀번호 역시 파일로부터 안전하게 읽어옵니다.
  • secrets: Docker Compose를 사용하여 민감한 데이터를 관리하는 가장 안전하고 권장되는 방법입니다.
    • 최상위 secrets 블록에서 시크릿의 이름(mysql_root_password)과 실제 비밀번호가 담긴 호스트의 파일 경로(file: ./secrets/...)를 정의합니다.
    • 서비스(mysql) 내의 secrets 블록에서 사용할 시크릿의 이름을 참조하면, docker-compose는 호스트의 비밀번호 파일 내용을 읽어 컨테이너 내부의 /run/secrets/<시크릿_이름> 경로에 임시 파일을 생성하여 마운트합니다.
    • 이 메커니즘 덕분에, MYSQL_ROOT_PASSWORD_FILE 환경 변수가 /run/secrets/mysql_root_password 파일을 읽어 비밀번호를 설정할 수 있게 됩니다. 중요한 것은 비밀번호 파일 자체(secrets 디렉터리)를 절대로 Git과 같은 버전 관리에 포함해서는 안 된다는 점입니다.
  • volumes: 컨테이너가 삭제되더라도 데이터를 보존하기 위해 사용합니다. (3.5장 영속성 데이터 참고)
    • mysql_data:/var/lib/mysql: mysql_data라는 이름의 볼륨(Named Volume)을 컨테이너의 /var/lib/mysql 디렉터리(MySQL이 실제 데이터를 저장하는 경로)에 마운트합니다.
    • 최상위 volumes 블록에 mysql_data:를 선언함으로써 도커가 관리하는 영속적인 데이터 저장 공간을 생성합니다. 이를 통해 컨테이너를 재생성해도 모든 데이터베이스 정보는 그대로 유지됩니다.
  • ports: 호스트 컴퓨터와 컨테이너 간의 네트워크 포트를 연결합니다.
    • "3307:3307": 호스트 컴퓨터의 3307번 포트로 들어오는 요청을 컨테이너 내부의 3307번 포트로 전달합니다. 이를 통해 로컬 PC의 개발 도구에서 localhost:3307로 접속하여 컨테이너의 MySQL 서버에 연결할 수 있습니다.
728x90