前言
此篇幅內容較多,講解的很詳細,也有很多知識點。能耐心認真的讀完,就很不錯了~
如果你覺得此文章不錯的話,或者是根據此文檔進行安裝mysql的話,抽空在文檔最下方留個言吧讓我看到你的支持
Docker 中國官方鏡像加速
如果覺得國外下載速度太慢,可以配置一個“Docker 中國官方鏡像加速”,來提高鏡像下載的速度。
一般情況下,都會永久性的配置鏡像加速,在Linux中修改 /etc/docker/daemon.json 文件,填入以下內容:
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
如果daemon.json不存在的話,需要自己創建一下。
文件修改保存成功之后,記得重啟一下Docker服務,以便讓這個鏡像加速生效。
重啟Docker服務
我們在【在centos系統中安裝Docker】一節中講過Docker隨着服務器重啟自動啟動的內容,正好可以通過命令service docker restart來實現Docker服務的重啟。
然后我們在Linux中執行命令:
service docker restart
出現下圖所示結果,表明Docker服務已經重新啟動了!這樣就可以永久性的使用Docker加速服務了。
如果不做特別的配置的話,之前處於運行狀態的容器,隨着Docker服務的重啟也會停止運行。
下載mysql鏡像
docker pull mysql
如果配置了鏡像加速,那么在下載mysql鏡像或者其他比較大的文件的時候,會發現下載速度變得非常快!
啟動mysql容器
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql
其中 -e 的作用是用於設置環境變量,mysql默認用戶名為root,則MYSQL_ROOT_PASSWORD即為root設置密碼,即123456
查看運行的mysql容器
docker ps
如下圖:
mysql容器已經正常啟動了!
進入mysql容器
既然mysql服務啟動了,如果我們想對mysql進行操作(比如進入命令行操作、客戶端連接等操作),該怎么辦?
通過 docker exec 命令進入mysql容器:
docker exec -it c9 /bin/bash
其中的“c9”指的當前mysql容器ID的前面部分值(在上圖就可以看出來mysql容器的ID是 c94faeed480a)。
回車運行效果如下圖:
其實這個時候,命令行控制台可以輸入mysql相關的命令了。
連接mysql數據庫
mysql -u root -p123456
如下圖:
這個就是我們非常熟悉的mysql命令行界面了!
我們可以在這里創建數據庫、表等操作。再次印證了Docker的強大和方便!
查看當前所有的數據庫
在mysql命令行中執行命令:
show databases;
如下圖所示:
完全就是和平常使用mysql一樣。
創建數據庫、表、新增測試數據
- 創建數據庫
create database docker_test;
效果如下圖:
這里我就創建了一個數據庫docker_test
- 選擇數據庫
首先需要選擇具體的數據庫,執行命令選擇剛剛創建的數據庫:
use docker_test
- 創建表:
create table test(name varchar(20),age int(11));
創建了test表,有2個字段:name、age
- 添加測試數據:
insert into test values("Kitty",26),("Tom",18),("Jack",36);
這里就簡單添加3條測試數據。
我們查詢一下數據是否存在於數據庫中:
select * from test;
一切OK!
客戶端連接mysql數據庫
既然mysql成功啟動並運行,除了能在命令行中操作mysql數據庫之外,肯定也是必須要能在客戶端上連接和操作數據庫才行。
下面我就在我本地電腦上通過數據庫客戶端軟件連接一下這個mysql數據庫, 看看能不能正常連接和操作。
我使用的是DataGrip客戶端軟件,如果你們需要的話,可以下載使用 https://pan.baidu.com/s/1NkzEG_rjwFBylUSMxfIUzw
如果版本低的話,可以到官方下載最新版本 https://www.jetbrains.com/datagrip/
打開本地DataGrip客戶端,新建連接mysql數據庫
輸入正確的mysql相關信息,連接數據庫:
輸入完成之后,可以點擊下方的 Test Connection 按鈕,來測試連接是否正常。
查看創建的****數據庫和表:
到此,mysql的相關服務已經正常訪問和操作了。這和我們傳統的使用mysql沒有什么不同。
客戶端中操作表數據
我們通過DataGrip客戶端,在test表中手動再添加一條數據,然后我們在docker中看看是否能查看到新增的數據:
【注意】:我這里添加了一條帶有中文的數據。
進入mysql容器中查詢表數據
呀!是不是發現問題了~ 沒錯,中文亂碼!怎么解決呢?
mysql容器中解決表數據中文亂碼
查看mysql容器的ID:
進入mysql的docker容器:
docker exec -it c9 /bin/bash
編輯mysql配置文件:
vim /etc/mysql/my.cnf
如果提示 vim: command not found 的錯誤信息,需要安裝相關依賴包,執行下面兩個命令即可:
apt-get update
apt-get install vim
在my.cnf文件中加入以下配置:
[mysqld]
character-set-server=utf8
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
最終修改結果為:
重新進入mysql容器,查詢表數據,顯示結果為:
可以看到,已經正常顯示中文了!
停止並重啟mysql容器,再次查看效果
客戶端DataGrip重新連接mysql:
客戶端連接正常!
進入mysql容器,查看表數據:
mysql容器重啟之后,查詢數據正常顯示中文!一切沒什么問題了~
通過commit命令提交新的鏡像
根據在mysql容器中所做的更改,創建新的mysql鏡像。
回想一下,我們在mysql容器中做了什么更改?
創建數據庫、表、新增數據、修改my.cnf配置文件,就是這些吧~
使用commit命令****提交新鏡像
通過在Linux命令行中執行命令,提交新的鏡像:
docker commit c9 mysql-new
其中,“c9”就是指的容器ID,新的鏡像名稱為“mysql-new”。
如下圖:
查看所有鏡像列表:
是不是發現了我們創建的新的鏡像mysql-new了。
啟動新創建的mysql鏡像
由於上面我們已經運行了一個mysql的容器了,端口是3306,所以我們新運行一個mysql容器的時候,端口號就不能是3306了,這里我指定為3307,且容器的別名是mysql-new,方便區分查看。
進入新創建的mysql容器
-
查看mysql數據庫信息
-
查看my.cnf配置文件內容
從上面2張圖中,可以明顯的看到,我們之前創建的數據庫docker_test、表test,都沒有了!但是修改的my.cnf配置文件的內容還是保留着的。
why??? 為什么會這樣呢?
官方文檔在commit命令的介紹中,有這樣一段話:
The commit operation will not include any data contained in volumes mounted inside the container.
意思是commit操作並不會包含容器內掛載數據卷中的數據。
如果對於“數據卷”不了解的話,確實看不懂是什么意思。
數據卷與數據卷容器
生產環境中使用Docker的過程中,往往需要對數據進行持久化,或者需要在多個容器之間進行數據共享,這必然涉及容器的數據管理操作。
容器中管理數據主要有兩種方式:
數據卷(Data Volumes):數據卷是一個可供容器使用的特殊目錄,它將主機操作系統目錄直接映射進容器。
數據卷容器(Data Volume Containers):數據卷容器也是一個容器,但是它的目的是專門用來提供數據卷,供其他容器掛載使用的。
根據官方文檔對於commit的介紹中,可以猜測到為何之前創建的數據庫、表都不見了,原因是因為mysql容器的掛載數據卷引起的。
我們可以通過命令查看到別名是“mysql”的容器掛載數據卷的目錄。
看一下我們的“mysql”容器的ID信息,方便查看。
通過命令docker inspect查看mysql這個容器的數據卷掛載信息:
docker inspect c9
執行命令之后,由於顯示的內容比較多,這里我們就貼一下重要的信息:
通過圖中可以看到,mysql容器將容器內的/var/lib/mysql路徑作為volume掛載。真正的數據庫相關數據文件所在的目錄就是“Source”對應的目錄,即:/var/lib/docker/volumes/1b0b17f6a4f78d357a187116d75991db8ee784213e67cc9b9988c8ef647fe563/_data
我們可以進入mysql容器查看/var/lib/mysql目錄下的內容:
發現的確是mysql數據庫的數據文件(紅色區域)。
這時候,我們切換到Linux命令行,進入到mysql容器的數據掛載目錄,看看該目錄下有什么內容:
/var/lib/docker/volumes/1b0b17f6a4f78d357a187116d75991db8ee784213e67cc9b9988c8ef647fe563/_data
如下圖所示:
咦~ 是不是發現了什么!把黃色區域的內容與上圖中紅色區域內容進行對比,是不是內容一模一樣!
這也就印證了,當初我們在mysql容器中創建的數據庫、表等,真正的數據庫文件存放的位置就是在宿主機下面,而不是存放在容器中。
到此,我們終於知道了為何mysql-new容器中的數據庫、表都不見了,原來數據庫文件是存放在宿主機上的。
那該如何解決這個問題呢?怎樣才能讓mysql-new容器啟動之后可以正常加載我們之前創建的數據庫、表等數據呢?這就引入了下面的正題 —— 數據掛載。
數據掛載
docker的數據掛載分為三種,volume、bind mount和tmpfs,關於三種的具體說明,有興趣了解的可以看一下官網的文檔 https://docs.docker.com/storage/
參考文檔 《基於docker部署mysql的數據持久化問題》 https://www.jianshu.com/p/530d00f97cbf
上面的文章里面,把問題描述的非常詳細清楚。我這里就不多做說明了。
使用 -v 實現數據掛載(數據卷)
如果我們想在 run 一個新的mysql容器的時候,可以正常訪問我們之前在mysql容器中創建的數據庫、表數據,則在docker run命令啟動容器的時候,就需要指定掛載目錄。
注意:要想讓新的mysql容器能正常掛載名稱是“mysql”容器,前提是需要先停止名稱是“mysql”的容器,不然的話,即使run命令配置正確,容器啟動的時候會一直報錯:
上圖就是因為沒有事先停止mysql容器導致的。
下面開始具體操作:
- 先停止mysql容器
- 重新啟動一個新的mysql容器,命令如下:
docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql-v -v /var/lib/docker/volumes/1b0b17f6a4f78d357a187116d75991db8ee784213e67cc9b9988c8ef647fe563/_data:/var/lib/mysql mysql
最重要的一個參數 -v :掛載數據卷。-v 后面的值中間有“:”號,前半部分指的是宿主機的目錄(也就是我們上面的mysql容器的數據庫存儲的目錄),后半部分指的是容器的目錄。
實現的效果就是說:新啟動的容器,掛載宿主機的目錄,實現數據共享。
運行結果:
登錄新的mysql-v容器,查看數據庫信息
直接看下圖的命令操作吧:
看到效果了吧!在這個mysql-v的新容器里面,已經可以看到我們一開始在“mysql”容器中創建的數據庫和表了。
也就實現了容器之間的數據共享。
核心的實現就是在run命令里面加入了 -v 參數。如果不太明白-v的含義的,可以自行網上查詢資料了解學習,加深印象。
上面我們解決了容器掛載數據卷的問題,但是細心的朋友,可能還有一個疑問:
為什么修改了my.cnf配置文件、以及運行mysql鏡像時指定的MYSQL_ROOT_PASSWORD=123456,卻依然可以在新容器mysql-new中使用呢,為什么這倆樣數據不會消失呢?
官方文檔對於commit命令還有這樣一段描述:
It can be useful to commit a container’s file changes or settings into a new image.
谷歌翻譯過來的意思就是:將容器的文件更改或設置提交到新映像可能很有用。
還記得我們當初運行第一個mysql容器的時候,docker run 命令是怎樣的,這里貼一下當時啟動容器的命令:
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql
其中,里面使用到了 -e 參數,設置了root用戶的密碼為123456。
所以,結合官方文檔對commit的介紹(It can be useful to commit a container’s file changes or settings into a new image. ),就可以知道,通過 -e 設置的信息,在使用commit提交新鏡像的時候,這些設置被容器保留了下來,commit命令使用這些設置構建了新的鏡像,在新容器里面使用的是相同的設置。
這也印證了,我們在mysql-new容器中登錄數據庫的時候,登錄密碼寫的是123456。因為在第一次啟動mysql服務的時候,用戶root密碼是通過 -e 指定的,所以在commit提交新的鏡像的時候,是被一同提交到了新鏡像mysql-new中。
數據卷容器
通過數據卷容器也可以實現多個容器間的數據共享。
如果要授權一個容器訪問另一個容器的數據卷,我們可以使用-volumes-from參數來執行docker run。
(這里就不多做說明了,有興趣的可以網上自行查閱資料研究)