[Docker] MySQL 8 server as docker container

What’s New in MySQL 8.0

在 COSCUP 上被洗腦 MySQL 8.0.
MySQL 8.0 大改版帶來大量新功能與更高的效能, 也產生相容性等問題, 商業實務要在生產環境上使用仍需評估. 但技術上諸多新特點真的令人心動, 故決定花些時間研究了解. MySQL 8.0 有相當多的改進, 以下列出我有興趣的項目, 其他新特點可以參考文末相關連結.

  • 性能: 根據官方文件顯示, MySQL 8.0 的速度比 MySQL 5.7 快上兩倍.

  • Window Functions, CTE: 許多現代 SQL 都提供窗口函式, 實現多行聚合計算, 並將計算後的結果附加到單行內. 如此可以提供新的查詢方式. Ex: rank()
    而 CTE 通用表示式可以把查詢語法更結構化, 透過迴查詢能寫出層次清晰的複雜查詢語法, 修改維護都更容易. 值得一提的是, 從 MySQL 分支出來的 mariadb 亦支援這兩個功能, 不過語法不一定通用就是了. MySQL 8 vs. MariaDB: Comparison of Window Functions and CTEs - DZone Database

  • JSON and Document Store: MySQL 5.7 開始支援原生 JSON 格式, 和 NoSQL 資料庫競爭. MySQL 8.0 除了擴充了對 JSON 的支援外, 亦加強了 JSON 查詢的效能. 而新的聚合函式則讓開發者在同一個查詢語法中, 結合 MySQL 原生結構化資料與 JSON 資料.
    MySQL 8.0 的文件儲存提供了 schema-less 的 JSON 資料更完整的 transcation 和 ACID 支援.

    MySQL 並推出了 X Dev API, 提供開發者透過更高階的物件操作語法來存取資料庫. 這是讓我決定花時間摸索 MySQL 8.0 的重要原因, 想把玩 X Dev API 只能弄個 MySQL 8.0 環境跑.

MySQL 8.0 as docker container

  1. Start a mysql server instance

    1
    $ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    • --name string Assign a name to the container
      • --name some-mysql the name you want to assign to your container
    • -e, --env list Set environment variables
      • MYSQL_ROOT_PASSWORD=my-secret-pw the password to be set for the MySQL root user
    • -d, --detach Run container in background and print container ID
    • mysql:tag docker image name
  2. Using a custom MySQL configuration file

    1
    $ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    • -v, --volume list Bind mount a volume
      • -v /my/custom:/etc/mysql/conf.d start a new MySQL instance uses the combined startup settings from /etc/mysql/my.cnf and /etc/mysql/conf.d/config-file.cnf, with settings from the latter taking precedence.
  3. Where to Store Data

    1
    $ docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

    mounts the /my/own/datadir directory from the underlying host system as /var/lib/mysql inside the container, where MySQL by default will write its data files.

  4. Access port

    1
    $ docker run --name some-mysql -p 3306:3306 -p 33060:33060 -v /my/own/datadir:/var/lib/mysql /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    • -p, --publish list Publish a container’s port(s) to the host
      • -p 3306:3306
      • -p 33060:33060 MySQL XDevAPI X Plugin listening to default port 33060

My MySQL 8.0 workspace setup

個人開發環境有幾個需求:

  1. 利用 Dropbox 保持工作資料在多電腦同步
  2. 開發環境帳密和生產環境使用的帳密不同
  3. 絕不透過 root 來存取 MySQL 資料

Setup working folder on Dropbox

關於第一個需求, 可把 mysql 的 data/log/config 等資料夾建立在 Dropbox 資料夾下即可.

1
2
mkdir ~/Dropbox/project/docker/mysql8/conf
mkdir ~/Dropbox/project/docker/mysql8/data

為了方便啟動與停止 container, 我另寫了幾個 shell scripts 放在 mysql8 資料夾下.

1
2
3
4
5
6
7
8
export MYSQL8_HOME="$KYWK_HOME/Dropbox/project/docker/mysql8"

#run service
docker run --name mysql8 -d -p 3306:3306 -p 33060:33060 \
-e MYSQL_ROOT_PASSWORD=pw123456 \
-v $MYSQL8_HOME/data:/var/lib/mysql \
-v $MYSQL8_HOME/conf:/etc/mysql/conf.d \
mysql
1
docker container restart mysql8
1
docker container stop mysql8

Setup root user PRIVILEGES

對於第二、三個設計需求, 新增一個 MySQL 使用者帳號即可.

MySQL image 預設 root 無法透過網路連線來 Grant 其他使用者權限. 可直接從進入 mysql container 去新增使用者. 或進入 mysql container 後把網路 GRANT 權限打開, 再透過網路新增設定其他使用者.

以上兩種方法都必須先進入 mysql container, 指令如下: $ docker exec -ti mysql8 mysql

為方便往後操作, 我選擇進入 container 後把 root@%Grant_priv 打開.

1
2
3
4
5
$ docker exec -ti mysql8 mysql -p

// at mysql shell
mysql> GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

如此一來, 即可 root 在外部連線狀況下來新增修改使用者權限. 較通用於各種 MySQL Client 工具.

Setup management user

Ex: 新增管理使用者

1
$ mysql -h 127.0.0.1 -u root -p < kywk.sql

1
2
3
4
5
6
use mysql
CREATE USER 'kywk'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'kywk'@'localhost' WITH GRANT OPTION;
CREATE USER 'kywk'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'kywk'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

MySQL 8 新增了角色管理 (Role) 的功能, 而設定使用者權限的語法也和 MySQL 5.x 不完全相容. 要翻翻文件.

後記

發文時研究 MySQL 8.0 及 XDev API 單純是技術上跟隨, 還未考慮運用到生產環境上. 一來目前工作上沒有足夠 IT 能量自行監控管理資料庫服務, AWS RDS 分攤了這部份需求. 二來 ORACLE 實在太惡名昭彰, 情感上想離他越遠越好啊.

最重要的, MySQL 8 的大改版, 新增很多功能外也造成不少問題. 在設置測試環境時, 就發生使用者權限設定語法不同及 Sequel Pro 無法連上 MySQL 8 伺服器的問題. 使用者權限管理語法查文件後已找到解法. Sequel Pro 的 Github 上也針對該 issue 進行修正, 發文時狀態為 Fixed-AwaitingRelease.

何時會在生產環境使用上 MySQL 8 尚未得而知, 也許經過幾篇踩雷心得後再說吧. 下篇來踩踩 MySQL X Dev API 的雷.