タグ: mysql

  • M1 mac で Dockerを使ってMySQL 5.7を外部から接続できるように設定する

    M1 mac で Dockerを使ってMySQL 5.7を外部から接続できるように設定する

     

    Dockerを使ってMySQL 5.7を外部から接続できるように設定する

    Dockerを使ってMySQLを簡単に起動する際、外部からの接続設定にちょっとしたコツが必要です。

    この記事では、その手順をシンプルにまとめています。

    1. 概要

    基本的には、MySQLの設定を変更して、どのホストからでも接続を受け入れるようにする必要があります。加えて、Dockerコンテナ内のMySQLユーザー設定も変更する必要があります。

    2. 手順

    以下のコードを実行します:

    git clone https://github.com/GitSumito/CodeArsenal.git
    cd CodeArsenal/mysql-external-access
    sh ./main.sh

     

    3. 詳細な手順の説明

    1. custom_my.cnf という設定ファイルを作成し、MySQLがどのホストからでも接続を受け入れるように bind-address を設定します。
    2. DockerでMySQLを起動します。この際、上で作成した custom_my.cnf をMySQLの設定ディレクトリにマウントします。
    3. MySQLが完全に起動するのを待ちます(この例では30秒待機していますが、環境によっては調整が必要です)。
    4. docker exec を使用してMySQLコンテナ内でユーザー設定を行います。この例では、任意のホストからの接続を受け入れるrootユーザーを作成しています。

    4. 注意点

    この設定は開発やテスト環境での利用を想定しています。セキュリティの観点から、本番環境での利用は推奨しません。特に、パスワードなしのrootユーザーを外部から接続できるようにする設定は、公開環境での利用は避けてください。

  • コンテナ内の mysql にリクエストされたクエリを確認する

    コンテナ内の mysql にリクエストされたクエリを確認する

    開発している際 コンテナの mysql にどのようなクエリ走ったのか確認したいことがある。

    スロークエリを 0秒に設定することで、DB にリクエストされた 全クエリを確認することができる。

    mysql> show variables like 'slow%';
    +---------------------+--------------------------------------+
    | Variable_name       | Value                                |
    +---------------------+--------------------------------------+
    | slow_launch_time    | 2                                    |
    | slow_query_log      | OFF                                  |
    | slow_query_log_file | /var/lib/mysql/5c364d250748-slow.log |
    +---------------------+--------------------------------------+
    3 rows in set (0.00 sec)
    
    mysql> 
    

    slow_query_log が OFF になっている場合、出力されない。

    set global slow_query_log_file = '/tmp/mysql-slow.log';
    set global long_query_time = 0;
    set global slow_query_log = ON;

    上記コマンドを実行し、再度確認すると、スロークエリが出力されるようになってる。

    mysql> show variables like 'slow%';
    +---------------------+---------------------+
    | Variable_name       | Value               |
    +---------------------+---------------------+
    | slow_launch_time    | 2                   |
    | slow_query_log      | ON                  |
    | slow_query_log_file | /tmp/mysql-slow.log |
    +---------------------+---------------------+
    3 rows in set (0.00 sec)
    
    mysql> 
    

    スロークエリが 0秒に設定されたか確認するのは

    show global variables like 'long_query_time';

    コマンドを実行する

    mysql> show global variables like 'long_query_time';
    +-----------------+----------+
    | Variable_name   | Value    |
    +-----------------+----------+
    | long_query_time | 0.000000 |
    +-----------------+----------+
    1 row in set (0.00 sec)
    
    mysql> 
    

    結果

    
    SET timestamp=1624328575;
    INSERT INTO `xxx_transactions` (`id`,`operation`,`request`,`requested_at`,`response`,`responsed_at`,`metadata`,`status`,`failure_code`,`failure_message`,`created_by`,`created_at`) VALUES (105,'request',NULL,NULL,NULL,NULL,NULL,'succeeded',NULL,NULL,'123456789','2021-06-22 02:22:55.1492209');

    無事流れたクエリを確認することができた。

  • SchemaSpy で SQLファイル からスキーマ情報を出せるようにした

    SchemaSpy で SQLファイル からスキーマ情報を出せるようにした

    tl;dr;

    ER図などを自動生成してくれる SchemaSpy というツールがある。
    このツールは接続先のDBを指定する事でそのDBサーバのスキーマ情報を読み取って解析してくれる作りだ。
    しかし、DBに接続させたくない場合は多い。手元にcreate table文などを盛り込んだDDL文の塊を用意する事で対応できるようにした。

    対処した事

    と言っても SchemaSpy 自体をいじったわけではなく、SQLファイルを手元に用意して、DBのコンテナに読み込ませ、そのコンテナに対して SchemaSpy を叩かせるようにしただけ。

    見えてきた未来

    DBをダイレクトに繋ぎに行かずにすむ事で、ブランチごとにDB構成を管理することができるようになり、CIに組み込めばスキーマのレビューもしやすくなる。

    考えなければならなかったところ

    SchemaSpy が動く前にDBコンテナに適切にデータが作られてないといけない。

    もしテーブルが作られていないと SchemaSpy が空振りしてしまい、期待している結果に至らないからだ。そのため、DBコンテナにテーブルが作られていることを確認してから SchemaSpy が動かす必要がある。

    しかし、docker-compose では、それ自体で細かな起動順番を指定することができない。

    docker 公式ドキュメントでも以下のような記載がある。

    Compose はコンテナの準備が「整う」まで待ちません(つまり、特定のアプリケーションが利用可能になるまで待ちません)。単に起動するだけです。

    http://docs.docker.jp/compose/startup-order.html

    自分で制御するしかないようだ。起動したい順番をシーケンス図でかくとこのような感じ。

    SchemaSpyコンテナ側での制御はシンプルにシェルで行っており、mysqlに繋がったら CREATE TABLE 含むDB側の準備は完了とみなし、SchemaSpy側の実際の処理をするようにした。

    #!/bin/sh
    
    set -e
    echo $@
    
    host=$1
    shift
    user=$1
    shift
    password=$1
    shift
    cmd="java -jar schemaspy.jar"
    
    echo "Waiting for mysql"
    until mysql -h"$host" -u"$user" -p"$password" &> /dev/null
    do
            >$2 echo -n "."
            sleep 1
    done
    
    >&2 echo "MySQL is up - executing command"
    exec $cmd

    https://github.com/GitSumito/schemaspy-with-sql/blob/master/docker/schemaspy/bin/wait.sh

    MySQLに繋がったらtableも作られていると解釈するのは危険ではないかと感じるかもしれない。

    これは  mysql のコンテナの設定を用いてもう少し説明したい。

    version: '3'
    
    services:
      nginx:
        image: nginx:latest
        container_name: schemaspy_nginx
        volumes:
          - ./schemaspy:/var/www/html:ro
          - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
        ports:
          - "80:80"
        environment:
          - LANG=ja_JP.UTF-8
          - TZ=Asia/Tokyo
    
      schemaspy:
        build: ./docker/schemaspy
        image: treetips/schemaspy-mysql
        container_name: schemaspy
        volumes:
          - ./schemaspy:/app/html:rw
          - ./docker/schemaspy/config/schemaspy.properties:/app/schemaspy.properties:ro
        environment:
          - LANG=ja_JP.UTF-8
          - TZ=Asia/Tokyo
        working_dir: "/app"
        depends_on:
          - mysql
        command: "sh -x /app/bin/wait.sh mysql docker docker employee java -jar schemaspy.jar"
    # also modify db info docker/schemaspy/config/schemaspy.properties
    
      mysql:
        image: mysql:5.7
        container_name: mysql_host
        environment:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: employee
          MYSQL_USER: docker
          MYSQL_PASSWORD: docker
          TZ: 'Asia/Tokyo'
          MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
        command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
        volumes:
          - ./docker/mysql/sql:/docker-entrypoint-initdb.d
        ports:
          - 3306:3306

    https://github.com/GitSumito/schemaspy-with-sql/blob/master/docker-compose.yml

    mysqlのvolumesでは

    `./docker/mysql/sql` を`/docker-entrypoint-initdb.d`へマウントするよう設定している。

    これはMySQLコンテナの仕様で、デフォルトでこのディレクトリの`.sh`ファイル、`.sql`ファイル、 `.sql.gz`ファイル があれば初期化段階で読み込み、MYSQL_DATABASEに指定したデータベースに作られる。

    Initializing a fresh instance

    When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh.sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.

    https://hub.docker.com/_/mysql

    念のためdocker-compose をupしてログを確認してみると、`mysqld: ready for connections.`になる前に、実行されている。

    mysql_host   | 2020-01-19 23:12:16+09:00 [Note] [Entrypoint]: Creating database employee
    mysql_host   | 2020-01-19 23:12:16+09:00 [Note] [Entrypoint]: Creating user docker
    mysql_host   | 2020-01-19 23:12:16+09:00 [Note] [Entrypoint]: Giving user docker access to schema employee
    mysql_host   | 
    mysql_host   | 2020-01-19 23:12:17+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/001-create-tables.sql
    (中略)
    mysql_host   | 2020-01-19T14:12:20.391989Z 0 [Note] mysqld: ready for connections.
    mysql_host   | Version: '5.7.29'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

    使ってみる

    githubに置いておいたので適宜clone

    git clone https://github.com/GitSumito/schemaspy-with-sql.git
    make build
    make up
    

     その後、自分のPCにhttp接続するとSchemaSpyが作ったアウトプットを見ることができる。schemaspy-1

    ER図はこのような感じ。非常に見やすい。

    なお、今回はMySQLで公開されているemployeeテーブルから一部情報を使って描写した。

    https://github.com/datacharmer/test_db/blob/master/employees.sql

    手取り早く手元のDDLに置き換えたい場合は、

    schemaspy-with-sql/blob/master/docker/mysql/sql/001-create-tables.sql

    ファイルの中身を変更してdocker-composeを起動するだけでSchemaSpyを起動させることができるようにしてある。

    最後に

    Migraiton ファイルをそのまま読み込ませることができればもっと便利になると思うので、次回はその対処を行いたいと思う。