본문으로 바로가기
728x90
반응형

목차

    개요

    Docker를 통해  MySQL을 사용 중이다.

     

    개인적으로는 MySQL Server을 Local에 설치해 사용하기엔 다소 거부감이 든다. Local에 MySQL Server를 설치하는 것이 다소 무거운 느낌이고 나중에 삭제를 한다고 해도 설치된 파일들을 일일이 찾아 제거하는 작업도 번거롭기 때문이다.

     

    MySQL Container를 그때그때 올리고 내리는 방식이 편하긴 하지만 아무래도 이렇게 사용하다 보면 Docker를 통해 MySQL을 사용하는 것이다 보니 기존에 MySQL Server에 설정해야 할 것이 "뭔가 다르게 해야 되지 않을까?"라는 궁금증이 생긴다.

     

    이번 포스팅은 필자가 Docker에서 MySQL의 사용하는데 유용하게 써먹었던 사항들에 대해 정리한 것이다.

    docker-compose.yml

    먼저 docker에서 mysql을 실행하기 위해 설정하는 부분이다. docker 자체를 이용하여 mysql을 실행하는 방법보다 필자는 docker-compose를 통해 MySQL을 사용한다.

     

    그래서 docker-compose.yml 파일을 특정 프로젝트의 루트 디렉터리에 만들어두고 docker-compose를 통해 MySQL Container를 올리면서 사용하고 있다.

    version: '3'
    services:
      local_db:
        image: mysql:5.7-debian
        platform: linux/amd64 # mac에서 docker를 사용할 경우 이 옵션은 반드시 활성화 되어야 합니다.
        ports:
          - "9901:3306"
        expose:
          - "9901"
        environment:
          MYSQL_ROOT_PASSWORD: 1234
          MYSQL_DATABASE: sample
        command:
          - --character-set-server=utf8
          - --collation-server=utf8_general_ci

    필자는 Mac M1 (Ventura 13.5)에서 Docker의 MySQL를 사용 중이기 때문에 platform 부분에 "linux/amd64"를 따로 기술하여 사용하고 있다. OSX가 아닌 환경에서는 해당 옵션을 기술할 필요는 없을 것이다.

     

    그 외에는 MySQL 환경에 관련된 기초적인 부분인 "port", "mysql_password" , "mysql_database_name", "character set"에 관련된 부분이다.

    참고로 위와 같이 mysql을 사용하는 경우 mysql user은 "root"로 설정된다

     

     

    docker-compose를 실행하면서. sql 파일을 실행하려면?

    어떤 경우에는 MySQL에 미리 준비된. sql 파일을 적용하여 특정 환경을 세팅할 수도 있다. 이는 준비되어 있는. sql 파일이 존재하는 경우 MySQL Container를 실행하면서 어떻게 적용시킬 것인가에 관련된 문제이다.

     

    필자는 이러한 경우 Dockerfile을 이용한다. 이해를 위해 프로젝트 루트에 다음과 같이 파일이 있다고 가정해 보자.

    - init-db.sh
    - migrate.sql : db에 적용되어햘 sql 파일
    - dockerfile
    - docker-compose.yml

     

    위 구성에서 dockerfile의 내용은 다음과 같다.

    FROM mysql:5.7
    
    ENV MYSQL_ROOT_PASSWORD=1234
    ENV MYSQL_DATABASE classicmodels
    
    WORKDIR /
    
    ADD init-db.sh /docker-entrypoint-initdb.d
    
    CMD ["mysqld"]

    MySQL Container안의 "docker-entrypoint-initdb.d" 디렉터리에 "init-db.sh"라는 shell script 파일을 넣어두면 docker-compose를 실행할 때 MySQL Container가 "docker-entrypoint-initdb.d" 디렉터리 안의 shell script 파일을 실행한다. 이때 init-db.sh 파일의 내용은 다음과 같다.

    # init-db.sh
    /usr/bin/mysql -uroot -p1234 classicmodels < /mysqlsampledatabase.sql

    여기까지 구성한 경우 docker-compose.yml에는 "build"라는 항목이 추가된다.

    version: '3'
    services:
      local_db:
        image: mysql:5.7-debian
        platform: linux/amd64
        build: # 추가된 항목
          context: .
        ports:
          - "9901:3306"
        expose:
          - "9901"
        command:
          - --character-set-server=utf8
          - --collation-server=utf8_general_ci

     

     

    docker-compose로 MySQL Cotainer를 실행한 경우 SQL Logging

    DataBase에서 SQL Logging이라고 하면 대부분 Slow Query에 대한 내용이겠지만 여기서는 MySQL Container에서 실시간으로 발생하는 SQL에 대한 Logging을 의미한다. 제일 처음 생각난 건 "docker-compose up"을 통해 MySQL Container를 올리게 되면 그 자체로 SQL Logging이 가능한지 찾아보려 했지만 필자는 그러한 방법을 찾지 못했다.

     

    그러하여 일반적으로 사용하는 MySQL의 SQL Logging 방법을 docker-compose.yml에다 적용했다.

    # ╰─$ cat docker-compose.yml
    version: '3'
    services:
      local_db:
        image: mysql:5.7-debian
        platform: linux/amd64
        ports:
          - "9901:3306"
        expose:
          - "9901"
        environment:
          MYSQL_ROOT_PASSWORD: 1234
          MYSQL_DATABASE: fastapi
        command:
          - --character-set-server=utf8
          - --collation-server=utf8_general_ci
          - --general-log=1 # SQL Logging을 확인하기 위해 추가한 라인
          - --general-log-file=/var/log/sql.log # SQL Logging을 확인하기 위해 추가한 라인

     위의 docker-compose.yml에 SQL Logging을 위해 추가된 옵션을 보면 단순히 log 파일의 위치를 변경한 것뿐이다. 이제 아래와 같이 docker 명령을 이용해 SQL Logging을 할 수 있다.

    ╰─$ sudo docker exec -it {CONTAINER_NAME} tail -f /var/log/sql.log

    결과는 다음과 같은 형태이다.

     

     

    DataBase Monitoring for Terminal 

    가볍게 terminal에서 DataBase에 대한 Monitoring을 할 수 있는 방법이 뭐가 있는지 조사해 보던 찰나에 알아낸 방법이다.


    "mytop"이라는 tool이며 Mac에서는 다음과 같이 설치가 가능하다.

    $ brew install mytop

    mytop은 "~/. mytop"이라는 파일을 기준으로 실행되는 모양이다. ~/. mytop에는 다음과 같은 내용이 들어간다.

    # ~/.mytop
    user=
    pass=
    host=
    db=
    delay=
    port=
    socket=

    mytop은 특이하게 remote로도 실행이 가능했는데 mysql container가 구동되어 있는 경우에 다음과 같이 실행할 수 있다.

    ╰─$ mytop -u root -p 1234 -h 127.0.0.1 --port 9901 -s 10

    위 argument 중 "-s"는 새로고침 빈도이다. 실행 결과는 다음과 같다.

    각 Metric에 대한 지표는 다음과 같다.

    Queries 서버에서 처리한 총쿼리의 숫자
    qps  초당 평균적으로 처리하는 쿼리 개수
    Slow 초당 평균 슬로 쿼리 수
    Se/In/Up/De(%) SELECT, INSERT, UPDATE, DELETE 쿼리문이 차지하는 각각의 백분율

     

     

    Sorts 실행 중인 쿼리 중에서 정렬 작업이 얼마나 많이 수행되었는지를 나타냄
    qps now 현재 실행 중인 쿼리의 초당 실행 횟수를 나타낸다 (Queries Per Second)
    Slow qps 초당 느린 쿼리의 실행 횟수를 나타낸다(Slow Queries Per Second)
    Threads 활성화되었거나 캐싱된 스레드

     

    Key Efficiency (테이블 캐시를 활용하여) 인덱스 검색을 얼마나 효율적으로 수행했는지를 나타낸다. 높을수록 인덱스를 효율적으로 활용하고 있다는 것을 의미한다. 반대로 낮은 경우 인덱스 검색에 대한 히트가 낮다는 것을 나타낸다.
    Bps in/out 초당 데이터베이스로 들어오고 나가는 데이터 양을 의미한다. (클라이언트에서 데이터베이스 서버로의 전송속도를 의미한다)
    Now in/out 실시간으로 데이터베이스 서버에 들어오고 나가는 실시간 데이터 양을 의미한다. 데이터베이스의 활동이나 네트워크 부하가 급격하게 번하는 경우 이를 참고하자.

     

     

    Trouble Shootting

    mytop을 설치한 후 실행했다가 다음과 같은 에러를 만났다.

    ╰─$ mytop
    Can't load '/opt/homebrew/Cellar/mytop/1.9.1_12/libexec/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/opt/homebrew/Cellar/mytop/1.9.1_12/libexec/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle, 0x0001): Library not loaded: /opt/homebrew/opt/mysql-client/lib/libmysqlclient.21.dylib
      Referenced from: <D4C74287-6407-35FE-885F-E3FFDC4F3751> /opt/homebrew/Cellar/mytop/1.9.1_12/libexec/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle
      Reason: tried: '/opt/homebrew/opt/mysql-client/lib/libmysqlclient.21.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/mysql-client/lib/libmysqlclient.21.dylib' (no such file), '/opt/homebrew/opt/mysql-client/lib/libmysqlclient.21.dylib' (no such file), '/usr/lib/libmysqlclient.21.dylib' (no such file, not in dyld cache), '/opt/homebrew/Cellar/mysql-client/8.1.0/lib/libmysqlclient.21.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/Cellar/mysql-client/8.1.0/lib/libmysqlclient.21.dylib' (no such file), '/opt/homebrew/Cellar/mysql-client/8.1.0/lib/libmysqlclient.21.dylib' (no such file), '/usr/lib/libmysqlclient.21.dylib' (no such file, not in dyld cache) at /System/Library/Perl/5.30/darwin-thread-multi-2level/DynaLoader.pm line 197.
     at /opt/homebrew/Cellar/mytop/1.9.1_12/libexec/bin/mytop line 20.
    Compilation failed in require at /opt/homebrew/Cellar/mytop/1.9.1_12/libexec/bin/mytop line 20.
    BEGIN failed--compilation aborted at /opt/homebrew/Cellar/mytop/1.9.1_12/libexec/bin/mytop line 20

    https://github.com/orgs/Homebrew/discussions/1381에서 perl을 다시 설치하고 진행하라는 내용을 보고 적용하여 해결했다.

     

     

    맺음말

    그동안 Docker에서 MySQL을 사용하기 위해 여러 시도들을 해왔는데 매번 큰 시간을 들였었다. 그렇게 매번 큰 시간을 들이고 나서 결과를 보면 큰 이득을 보진 못했는데 오늘 정리한 내용을 보면 나름대로 흡족하다.

     

    이 포스팅에 기재한 내용은 지극히도 필자 개인의 관점에서 추후 참고할만한 내용을 정리한 것이다. 크게 3가지 부분밖에 없는 것 같지만 소박하게 누군가에게 도움이 되었으면 싶은 마음을 남기면서 이만 글을 마치겠다.

    728x90
    반응형