Docker MySQLコンテナとWorkbenchでデータ設計環境を構築する

やりたいこと

  • WorkbenchのGUIで構築、でもローカルのDBを使いたくない
  • MySQLコンテナのDBでデータ設計
  • MySQLコンテナのデータを永続化
  • MySQLコンテナのMySQLのクエリログを残したい
  • 設計が終わったらWorkbenchでER図を出力

Github

github.com

作業

0 ローカルのMySQLを停止

  • Ubuntu機はMySQL自動起動しているので3306が使用されている。そのためMySQLコンテナ起動時にconflictするので停止する。
  • Workbenchが起動時に自動でローカルの3306と接続するので、3306を使いたい。
  • 以下にあるようにUbuntu16以上は systemctl または service コマンドを利用する。

Ubuntu 16 or higher

  • ちなみに service コマンドはラッパーのようなもので、高レベルコマンド。異なるLinux system間での共通インタフェース。 systemctl は実際のサービスをmanageする実体となるスクリプト

serverfault.com

service is an "high-level" command used for starting and stopping services in different unixes and linuxes. Depending on the "lower-level" service manager, service redirects on different binaries. For example, on CentOS 7 it redirects to systemctl, while on CentOS 6 it directly calls the relative /etc/init.d script. On the other hand, in older Ubuntu releases it redirects to upstart service is adequate for basic service management, while directly calling systemctl give greater control options.

  • systemctl コマンドに慣れてない。うろ覚え過ぎて sysctlと勘違いしてた。カーネルパラメータいじるコマンドと似た名前にするのやめて

dev.mysql.com

0-1 systemctlコマンド

  • systemctlがtabですぐに出せないから嫌い
  • サービス名が myslqd では起動できず、mysql.service。サービス名設定?みたいのあるのかもだけど本題でないのでそのまま
systemctl start mysql.service

systemctl status mysql.service
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: active (running) since 月 2019-09-23 11:55:48 PDT; 20s ago

0-2 serviceコマンド

  • サービス名が mysqld じゃなく mysql
service mysql start

service mysql status
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: active (running) since 月 2019-09-23 11:51:07 PDT; 2s ago

0-3 実際に停止

  • ローカルMySQL停止
systemctl stop mysql.service

● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since 月 2019-09-23 12:00:06 PDT; 7s ago

1 データの永続化

Containers are ephemeral in nature. They have a filesystem of their own. When containers die, the data stored locally in their filesystem is also gone.

www.ethernetresearch.com

  • ↑の記事には方法が2つとあるが、楽な共有ディレクトリを作るMethod2で永続化する

1-1 マウントするディレクトリ作成

ホスト側に共有ディレクトリ用のディレクトリを作成

mkdir mysql-data-dir

1-2 共有ディレクトリを指定して起動

起動。ホストから共有ディレクトリを確認、たしかにMySQL関連のファイルがあるのがわかる。

docker run -d --name mysql-server \
-e MYSQL_ROOT_PASSWORD=password \
-v ${path}/mysql-data-dir:/var/lib/mysql \
mysql:5.7.21
docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
1113f9beb233        mysql:5.7.21        "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        3306/tcp            mysql-server
ll mysql-data-dir
合計 185M
drwxr-x--- 2 guest-br046x guest-br046x 4.0K  9月 23 18:31 mysql
drwxr-x--- 2 guest-br046x guest-br046x 4.0K  9月 23 18:31 performance_schema
drwxr-x--- 2 guest-br046x guest-br046x  12K  9月 23 18:31 sys
-rw-r----- 1 guest-br046x guest-br046x   56  9月 23 18:31 auto.cnf
-rw------- 1 guest-br046x guest-br046x 1.7K  9月 23 18:31 ca-key.pem
-rw-r--r-- 1 guest-br046x guest-br046x 1.1K  9月 23 18:31 ca.pem
-rw-r--r-- 1 guest-br046x guest-br046x 1.1K  9月 23 18:31 client-cert.pem
-rw------- 1 guest-br046x guest-br046x 1.7K  9月 23 18:31 client-key.pem
-rw-r----- 1 guest-br046x guest-br046x 1.4K  9月 23 18:31 ib_buffer_pool
-rw-r----- 1 guest-br046x guest-br046x  48M  9月 23 18:31 ib_logfile0
-rw-r----- 1 guest-br046x guest-br046x  48M  9月 23 18:30 ib_logfile1
-rw-r----- 1 guest-br046x guest-br046x  76M  9月 23 18:31 ibdata1
-rw-r----- 1 guest-br046x guest-br046x  12M  9月 23 18:31 ibtmp1
-rw------- 1 guest-br046x guest-br046x 1.7K  9月 23 18:31 private_key.pem
-rw-r--r-- 1 guest-br046x guest-br046x  451  9月 23 18:31 public_key.pem
-rw-r--r-- 1 guest-br046x guest-br046x 1.1K  9月 23 18:31 server-cert.pem
-rw------- 1 guest-br046x guest-br046x 1.7K  9月 23 18:31 server-key.pem

2 port forwarding

  • ローカルの 3306MySQLコンテナの 3306 へport forwardingする
docker run -d -p 3306:3306 --name mysql-server -e MYSQL_ROOT_PASSWORD=password mysql:5.7.21
docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
09639fd616ea        mysql:5.7.21        "docker-entrypoint.s…"   6 seconds ago       Up 3 seconds        0.0.0.0:3306->3306/tcp   mysql-server

3 MySQLコンテナのログ設定

3-1 MySQLコンテナで必要なコマンドをインストールする

  • minminimalインストールなので、まず必要なコマンドをインストールする
  • ちなみに ps コマンドのインストールむずかった
docker exec -it mysql-server bash
apt-get update
apt-get install vim

stackoverflow.com

apt-get install procps

3-2 mysqldが参照しているmy.cnfを確認する

  • 以下の順番でmy.cnfを読み込んでいく
  • /etc/my.cnf が思い出しやすいので、 /etc/my.cnf を作成する

/etc/my.cnf Global options

SYSCONFDIR/my.cnf Global options

$MYSQL_HOME/my.cnf Server-specific options

defaults-extra-file The file specified with --defaults-extra-file=path, if any

~/.my.cnf User-specific options (in your home directory)

dba.stackexchange.com

# find / -name my.cnf
find: '/proc/1/map_files': Permission denied
/var/lib/dpkg/alternatives/my.cnf
/etc/alternatives/my.cnf
/etc/mysql/my.cnf

3-3 /etc/my.cnfを作成しログの設定を行う

  • my.cnfを編集して再起動するとコンテナ停止し、その後起動できない
  • 結局、docker-compose.ymlを用意してホストと共有することに
touch /etc/my.cnf
vim /etc/my.cnf

以下の内容を追記

[mysqld]
log = /var/log/mysql/query.log

4 docker-compose.ymlでまとめる

  • 結局、my.cnfロードできないのでdocker-compose.ymlを作ることに変更
  • 1から3までの内容をdocker-composeに集約する

4-1 ホスト側の準備

  • cnfファイルを用意する
    • 全クエリログ出力を有効、ログファイルのパス指定
    • デフォルトのerror.logのパスもクエリログと同じにしておく
[mysqld]

log-error   = /var/log/mysql/error.log

general_log=ON
general_log_file = /var/log/mysql/log_output.log

4-2 docker-compose.ymlを作成

  • コンテナのlogディレクトリをマウントするのに手こずった。permissionの問題でvolumesだけでは参照できない。
  • 下記の記事にあるとおり、単純にowner変更

stackoverflow.com

version: '3'
services:
  db:
    container_name: db_pg
    image: mysql:5.7.21
    environment:
      - "MYSQL_ROOT_PASSWORD=password"
      - "MYSQL_DATABASE=pg_db"
    ports:
      - "3306:3306"
    volumes:
      - db_pg_data:/var/lib/mysql
      - ./test.cnf:/etc/mysql/mysql.conf.d/test.cnf
      - ./logs:/var/log/mysql
    entrypoint: ""
    command: bash -c "chown -R mysql:mysql /var/log/mysql && exec /entrypoint.sh mysqld"

volumes:
    db_pg_data:

5. MySQLコンテナ起動

docker-compose up

使い方

1 クエリログをターミナルでtailしておく

sudo tailf log_output.log

2 Workbenchを起動

mysql-workbench

3 Workbenchでデータモデリングしていく

  • Workbenchの横にターミナルのログを開きつつ作業していく。Workbenchだけでもいいんだけど
  • Workbenchについては以下のエントリを参照

mizushou.hatenablog.com