Docker 玩轉 MySQL
Last updated on Apr 19, 2020 in 用 Docker 架設服務 by Amo Chen ‐ 3 min read
MySQL 是世界知名的關聯式資料庫(RDBMS),相當多應用(Application)背後都是以 MySQL 作為後端資料庫,是除了 PostgreSQL 之外的另一選擇。
MySQL 官方也提供 Docker 映像檔(image)讓人可以輕鬆透過 Docker 運行容器化的 MySQL 。
本文記錄如何使用 Docker hub 上的 MySQL 。
本文環境
- macOS 10.14
- Docker Desktop Community 2.1.0.2 (download link)
MySQL 版本
目前 MySQL 官方提供 5.5, 5.6, 5.7 以及 8.0 共 4 種版本的資料庫,可以在 pull Docker image 時指定相對應的 tag ,就能夠使用對應版本的 MySQL , tag 列表可以參閱 連結 。
例如本文使用 MySQL 8.0 版,其對應的 tag 為 8.0
,因此可用以下指令 pull image:
$ docker pull mysql/mysql-server:8.0
運行 MySQL
下載完成 image 後,可執行以下指令啟動 MySQL:
$ docker run --name=mysql8 -d -p 3306:3306 mysql/mysql-server:8.0
--name=mysql8
將 container 命名為 mysql8
-d
將 container 以背景(background)模式運行
-p
將 host 的 3306 port 導向至 container 的 3306 port, 如此一來,我們連線至 127.0.0.1:3306 便可直接連到 MySQL container
如果上述指令成功,可以用 docker ps
指令看到類似以下的執行結果:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
501a59352391 mysql/mysql-server:8.0 "/entrypoint.sh mysq…" 3 seconds ago Up 1 second (health: starting) 0.0.0.0:3306->3306/tcp, 33060/tcp mysql8
登入 MySQL
Docker 版本的 MySQL 預設會隨機產生 root
密碼,因此必須查詢 log 才能得知密碼為何。
可用以下指令撈出 root
的密碼:
$ docker logs mysql8 2>&1 | grep GENERATED
執行成功的話可以看到類似以下的訊息:
[Entrypoint] GENERATED ROOT PASSWORD: 7IPAv[UPCURoGMAHujEx$uH8uPr
此時的 root 帳號只接受 container 內的本機(localhost)登入,所以我們以指令試著登入 MySQL:
$ docker exec -it mysql8 mysql -uroot -p
接著輸入以下 SQL 更新 root 的密碼,這是由於 MYSQL_ONETIME_PASSWORD
環境變數預設是 true
導致我們必須變更密碼才能進一步使用:
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
如果不想這麼麻煩,可以改用以下指令直接設定 root 密碼:
$ docker run --name=mysql8 -d -p 3306:3306 --env MYSQL_ROOT_PASSWORD=myrootpassword mysql/mysql-server:8.0
如果連線到 docker 內的 MySQL 時遇到 Can’t connect to MySQL Server on ‘localhost’
之類的錯誤的話,多半是因為 root 帳號只開放來自 localhost 的連線,可以使用以下 SQL 改為開放外部連線(p.s. Production 環境請勿如此使用,將造成資安問題):
mysql> UPDATE mysql.user SET host='%' WHERE user = 'root' LIMIT 1;
針對 root 帳號重新設定 host 之後需要重新啟動 MySQL 的 container:
$ docker restart mysql8
如果覺得麻煩的話,可以新增 1 個開放外部連線的帳號:
mysql> CREATE USER 'newuser'@'%' IDENTIFIED BY 'password';
mysql> GRANT ALL ON your_database.* TO 'newuser'@'%';
更多可設定的環境變數(例如 MYSQL_DATABASE
MYSQL_USER
等)可參閱 Docker Environment Variables 章節。
資料庫資料存在哪裡?
由於 Docker container 預設並不會儲存任何資料,需要掛載 Volume 才有辦法將資料持久化(Persisting Data),而 Docker MySQL 也已經預設幫我們掛載 Volume ,因此資料庫內的資料並不會因為 Docker 重新啟動而消失,如果想知道 MySQL 的 Volume 路徑,可以用 docker inspect container_name
查看 Mounts
的部分,例如:
$ docker inspect mysql8
以下為 Mounts 資訊:
"Mounts": [
{
"Type": "volume",
"Name": "4f2d463cfc4bdd4baebcb098c97d7da3337195ed2c6572bc0b89f7e845d27652",
"Source": "/var/lib/docker/volumes/4f2d463cfc4bdd4baebcb098c97d7da3337195ed2c6572bc0b89f7e845d27652/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
如果是 macOS 的使用者會發現 /var/lib/docker/
找不到( no such file or directory: /var/lib/docker
),這是由於 macOS 的 Docker 是用 LinuxKit 模擬的,因此路徑又被包裝過一層,其大致在以下的路徑:
$ cd ~/Library/Containers/com.docker.docker/Data/vms/0/
可於上述資料夾內發現 tty
檔案,可以用 screen tty
指令,就能夠進入 LinuxKit 內,然後就能發現 /var/lib/docker/
資料夾,然後就能順利找到相對應的 Volume 囉!
References
https://dev.mysql.com/doc/refman/8.0/en/docker-mysql-more-topics.html