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 。

本文環境

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

對抗久坐職業傷害

研究指出每天增加 2 小時坐著的時間,會增加大腸癌、心臟疾病、肺癌的風險,也造成肩頸、腰背疼痛等常見問題。

然而對抗這些問題,卻只需要工作時定期休息跟伸展身體即可!

你想輕鬆改變現狀嗎?試試看我們的 PomodoRoll 番茄鐘吧! PomodoRoll 番茄鐘會根據你所設定的專注時間,定期建議你 1 項辦公族適用的伸展運動,幫助你打敗久坐所帶來的傷害!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!