寫在前面
Docker 是一個能夠把開發的應用程序自動部署到容器的開源引擎。Docker 提供了一個簡單、輕量的建模方式。掌握 Docker 以后,使用 Docker 安裝我們學習或者開發時常用的 mysql / redis / elastic search / rabbitMQ 等等會變得十分便捷。在作者嘗試用windows 7 電腦上的 Docker 容器部署 mysql 5.7 數據庫過程中,遇到了使用 sqlyog 卻連接不上 mysql 服務的問題。在第1小節中,我將演示一下如何使用 docker-compose 在 Docker 容器中啟動一個 MySQL 服務。第 2 小節,記錄的是我分析 Sqlyog 連接不上 Docker 容器中的 mysql 數據庫的原因。第 3 小節,則是闡述解決問題的方式。如果你只關心這個問題是如何解決的,請直接跳至“問題解決”章節。
作者在定位問題的過程中,接觸了 Docker 常用的指令,在本文中也稍稍做個記錄。另外,再開始 MySQL 部署之前,請確保你已經安裝設置好 Docker 環境了,可以參考這篇 Docker在WIN7上的配置
1.Docker 容器啟動 MySQL
Docker Mysql 官方文檔
Docker compose-file 官方文檔
相比於復雜的 docker 命令,我更願意選擇使用docker-compose方式在 Docker 容器中啟動 MySQL。
1.1 創建 yaml 文件
version: '3.1'
services:
test-mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- "3306:3306"
volumes:
- "/d/VirtualSpace/mysql/my.cnf:/etc/mysql/conf.d/my.cnf"
- "/d/VirtualSpace/mysql/:/docker-entrypoint-initdb.d/"
version
version 代表的是 Compose File Format(構成文件格式)的版本,有 1,2,2.x,3.x 版本,目前常見的是 3.x 版本(傳送門)
你可以通過 docker --version 命令查看一下你的 docker 是否支持對應的 Compile File Format 版本。
services
我認為,services 代表是服務進程,可以通過docker ps查看啟動進程。
這個名字的組成結構是 <當前工作路徑名>_<servicename>_<sequencenumber>,我的 docker-compose.yml 文件路徑是 D:\VirtualSpace\mysql\docker-compose.yml;服務名稱 servicename 是 test-mysql;序號 sequencenumber 是從 1 開始計數的。
想了解更多關於 servicename 的內容,可以查看 docker-compose service name和container name的關系
image
一般來說,比較推薦使用 Dockerfile 來構建鏡像,截止到 2020 年 11 月,MySQL 支持的鏡像標簽有以下幾種:
environment
啟動 mysql 映像時,可以通過在 docker run 命令行上傳遞一個或多個環境變量來調整 MySQL 實例的配置。
MYSQL_ROOT_PASSWORD
該變量是必需變量,它指定將為 MySQL root 用戶的密碼。
ports
要么指定兩個端口(HOST:CONTAINER),要么僅指定容器端口(選擇臨時主機端口)。
volumes
冒號左邊是指定主機的文件系統路徑,冒號右邊是指定容器的文件系統路徑。從基礎主機文件系統系統路徑,裝入容器文件系統路徑。
首次啟動容器時,將創建一個具有指定名稱的新數據庫,並使用提供的配置變量對其進行初始化。 此外,它將執行在/docker-entrypoint-initdb.d中找到的擴展名為.sh,.sql和.sql.gz的文件。文件將按字母順序執行。您可以通過將 SQL 轉儲安裝到該目錄中並為自定義圖像提供貢獻的數據來輕松填充 mysql 服務。 默認情況下,SQL 文件將導入到 MYSQL_DATABASE 變量指定的數據庫中。
關於 windows 系統的特殊說明:
我使用的是 win7 系統,在安裝 Docker 時,用到了 VirtualBox,Docker 其實是運行在 VirtualBox 中的
默認情況下,僅對C:\Users 目錄下進行掛載,對應的 Linux 虛擬機路徑是 /c/Users
因為我們在 docker-compose.yml 中有指定 /d/VirtualSpace/mysql/my.cnf 和 /d/VirtualSpace/mysql/,這其實是由你 Windows 主機上的 D:\VirtualSpace\mysql\my.cnf 和 D:\VirtualSpace\mysql 共享給虛擬機,然后再掛載到 Docker 容器。正因為共享給虛擬機了,所以虛擬機中也可以訪問到我們的指定文件。
1.2 啟動服務
docker-compose down
暫停所有的服務
docker-compose up
啟動當前工作目錄下的服務,docker-compose up -d 表示后台啟動命令。
1.3 使用 SQLyog 嘗試連接
然后在使用 SQLyog 連接時,主機地址選擇 localhost,端口 3306:
出現錯誤 1045,這是表示訪問密碼錯誤:
出現這個錯誤的主要原因:我以前在本地安裝過 mysql,所以這個其實是我 windows 主機安裝的 mysql 服務,不是 docker 容器的 mysql 服務,為了避開這個問題,我選擇修改了 docker-compose.yml 的 ports 屬性
ports:
- "3311:3306"
然后重新啟動服務。再次嘗試,這次的 Host Address 仍然是 localhost,端口改為 3311
2003 錯誤主要原因,網上的常見說法都是沒有啟動 mysql 服務。如果是 windows 主機安裝的 mysql 服務,只要啟動一下 mysql 服務就好了。但是,我們此時是用 Docker 容器啟動服務的。
2.問題分析
真的會是 Docker mysql 服務沒有正常啟動的原因嗎?
docker ps
該命令可以查看 Docker 服務進程。
分析:我們看到 test-mysql 服務是正常啟動的,而且端口也是正確的。
難道說端口映射不起作用?於是我百度了一下,找了好久,這篇文章(解決無法對docker容器進行端口映射的問題)終於解答了我的疑惑。
網上還有一種說法,說是沒有給 root 賬號授權。
docker exec
docker exec 命令允許您在 Docker 容器內運行命令。 以下命令行將在 mysql容器內為您提供 bash 外殼:
docker exec -it mysql_test-mysql_1
在 Bash 中登錄 mysql 客戶端
mysql -uroot -p123456
在 mysql 客戶端查詢用戶權限
SELECT HOST,USER,PLUGIN FROM mysql.user;
這里默認是給 host 授權了的,所以至少我連不上不是因為 root 賬號沒有授權的緣故。
3.問題解決
之所以在 Windows 主機上出現端口映射“不起作用”的情況,是因為在Linux上,docker 守護進程(和您的容器)在 Linux 機器本身上運行,因此“localhost”也是容器在其上運行的主機,並且端口已映射到該主機。
相對地,在 Windows(和 OS X)上,docker 守護程序和您的容器無法在本地運行,因此只有 docker 客戶端在 Windows 機器上運行,而守護程序(和您的容器)在運行Linux的 VirtualBox 虛擬機中運行。於是我們通過以下命令:
docker-machine ip default
找到這個Linux的ip地址,一般情況下這個地址是 192.168.99.100。
因此 Host Address 改為 192.168.99.100:
總結一下:
在 Windows(和 OS X)系統上,docker 守護程序和您的容器無法在本地運行,因此只有 docker 客戶端在 Windows 機器上運行,而守護程序(和您的容器)在運行Linux的 VirtualBox 虛擬機中運行。