Docker新手教程(07)Docker與MySQL

0七、Docker與MySQL

一、場景說明和使用思路

場景說明:mysql

既然說服務器,怎麼能離開各類數據庫呢?而 MySQL 顯然是最好用的數據庫之一。git

可是博主本身經驗來講,最討厭配 MySQL 的環境了,還好有 Docker 能夠簡單解決這個問題。github

使用思路:sql

Docker的容器是能夠被刪除、複製的。docker

但顯然,MySQL 做爲一個數據庫,是不能接受這樣的狀況發生(由於會致使數據丟失)。shell

初步的解決思路,是容器負責業務邏輯,而存儲數據存儲於容器外。數據庫

這樣,便實現了業務代碼(指 MySQL 的邏輯部分)與數據(指數據文件)分離的效果。express

其餘說明:安全

爲了方便省事,使用 MySQL5.6 版本。bash

由於 5.7 版本,會有一些很麻煩的事情出現。

二、生成MySQL容器

2.一、拉取MySQL鏡像

命令:

docker pull mysql:5.6
複製代碼

效果:

拉取了 MySQL 5.6 版本最新的 image

[root@qq20004604 ~]# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
docker-demo-01-express   0.0.1               416f1050c9bf        42 hours ago        907MB
mysql                    5.6                 98455b9624a9        2 weeks ago         372MB
複製代碼

2.二、生成一個MySQL容器

命令:

docker container run --name [name] -p 3306:3306 -e MYSQL_ROOT_PASSWORD=[password] -d mysql:[version]
複製代碼

示例代碼:

docker container run --name mysql-demo -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234567890 -d mysql:5.6
複製代碼

說明:

  • docker container run:經過image啓動容器,也能夠寫爲 docker run,但推薦使用更全的命令;
  • --name [name]:生成的容器的名字,若是不寫,則會隨機生成一個名字;
  • -p 3306:3306:將容器端口映射本機端口;
  • -e MYSQL_ROOT_PASSWORD=[password]:設置環境變量,這裏指設置 MySQL 的默認密碼。注意,不須要帶括號也不須要帶引號來包裹密碼;
  • -d mysql:[version]:這裏指你基於哪一個 MySQL 來生成容器;

示例代碼如上,效果是:

  • 生成一個MySQL容器,容器名字是 mysql-demo
  • 容器是基於 MySQL 5.6 的 image 生成的;
  • 能夠經過訪問主機的端口 3306 來訪問容器裏的 MySQL;
  • MySQL 的初始密碼是1234567890;

2.三、進行一些配置

首先,咱們一般須要遠程訪問,因此要配置一下。

進入容器的 MySQL:

  • docker container ps -a 列出全部容器;
  • 而後 docker container exec -it [containerID] /bin/bash 進入容器並輸入命令行;
  • 此時已經進入容器了;
  • mysql -u root -p 進入mysql,會提示輸入密碼,輸入密碼便可(若是按我上面示例代碼,默認密碼是 1234567890

對 MySQL 進行配置:

容許 MySQL 被遠程訪問:

grant all privileges on *.* to 'root'@'%' identified by '[password]';
flush privileges;
複製代碼
  • [password]:是密碼,他被引號所包含在內,容許任何一個 IP 訪問 root 帳號經過上面這個密碼;
  • 第二行是刷新上面這行配置;
  • 注意,本機訪問密碼和這裏的訪問密碼是獨立的(互不干擾);

此時狀況:

能夠在其餘機子上遠程訪問 MySQL,遠程訪問命令:

mysql -h [serverIP] -P 3306 -u root -p 
複製代碼

而後輸入密碼便可登陸進去了


其餘:

  1. 若是有相似 the 'information_schema.session_variables' feature is disabled 這樣的報錯,嘗試使用 set @@global.show_compatibility_56=ON; 來解決。一般是由於使用 5.7 版本而不是 5.6 版本而出現的;

2.四、將 MySQL 數據放在容器以外

等等,雖然 MySQL 跑起來了,可是數據還在容器裏呀?

解決方法很簡單,將容器內外 link 起來便可。

核心方法是建立容器時,經過參數:-v [容器外路徑]:[容器內路徑] 來實現。

這樣當容器內路徑(該文件夾)下內容有所改動時,會被同步到容器以外。

#### 2.五、測試收尾,移除舊的 MySQL 容器:

  • 先執行 docker containers ps -a 查到全部容器,而後找到測試用的容器的 ID;
  • 再執行 docker rm [containerID] 刪除測試容器;

### 三、數據持久化

命令:

docker run --name mysql-demo -v $PWD/mysqldata:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234567890 mysql:5.6
複製代碼

說明:

  • 基於 MySQL 5.6 持久化生成容器;
  • 關鍵命令是:-v $PWD/mysqldata:/var/lib/mysql
  • 此時 MySQL 的數據,既保存在容器內,也保存在容器外;
  • 容器外本機目錄爲:$PWD/mysqldata,即當前目錄下($PWD)的 mysqldata 文件夾下;
  • 容器內目錄是 /var/lib/mysql(這個是 MySQL 默認目錄);
  • 其餘以前都寫了,略;

四、持久化 + SQL預執行

理論上來講,咱們指望 Docker 鏡像生成容器並啓動完畢後,咱們就不須要進行管理了。

但實際上來講,不少時候並不能知足這樣的要求。

以 MySQL 爲例,一些權限管理、庫表預建立之類的事情,並不能在建立的時候就實現。

而且在我實際實踐中,MySQL 5.6 在做爲 咱們自定義的 Docker 的基礎鏡像時,雖然能夠正常運行。但若是生成容器時添加了持久化配置,卻會提示權限錯誤沒法正常運行。

由於這樣的緣由,我決定將本來一次性操做(生成鏡像後自動執行腳本),拆分爲兩步:

  1. 基於 MySQL 5.6 的鏡像,使用持久化配置;
  2. 生成容器後,手動執行腳原本實現預先配置;

3.1 預先準備內容

避免手動執行命令,所以咱們應該預先準備一些腳本。

先列出文件目錄:

create-image-mysql.sh    # 運行這個腳本建立容器
app                       # 用於在容器內執行的內容放這裏
|--init.sh                # shell腳本,在這裏將上面的SQL文件執行
|--data.sql               # 預建立數據庫表SQL,用於在數據庫初始化後,建立一些須要的database和table
|--privileges.sql         # 權限管理SQL,相關權限管理的SQL寫在這裏
複製代碼

其中:

  • create-image-mysql.sh:這個腳本將於用於建立容器、建立數據持久化文件夾、將數據拷貝進容器並執行腳本;
  • app:這個文件夾內容將被拷貝進腳本,具體功能將在下面解釋;

3.二、create-image-mysql.sh 建立管理容器

初始狀況下,咱們只有一個下載好的 MySQL5.6 鏡像(甚至都木有這個鏡像,但這個耗時就過久了)。因此這個腳本要作的事情不少,包括下載image,建立容器,將容器外腳本拷貝進容器,執行初始化腳本等。

文件內容:

#!/usr/bin/env bash
# 若是須要使用其餘鏡像,記得自行修改腳本
# 修改映射到本機的端口也同樣

appfilename="app"
mysqldatafilename="mysqldata"
imagename="docker-demo-02-mysql:0.0.1"
containername="mysql-demo"

# 創建持久化文件夾
if [ ! -d $mysqldatafilename ]; then
  mkdir "$mysqldatafilename"
fi

echo "【1】下載 mysql:5.6.43 版本 image"
docker pull mysql:5.6.43
echo "下載完成或無需下載"

echo "【2】先用本來鏡像生成容器,初始化不須要密碼(後續添加),並進行持久化配置"
echo "$PWD/$mysqldatafilename"
docker run --name "$containername" -d -v "$PWD/$mysqldatafilename":/var/lib/mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=yes mysql:5.6.43

# 若是本身手動執行的話,下面這行腳本能夠在建立容器時即添加帳號密碼
#docker run --name mysql-demo -d -v "$PWD/$mysqldatafilename":/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234567890 mysql:5.6.43

# 而後把 app 文件拷貝到容器裏面
echo "【3】而後把 app 文件拷貝到容器裏面"
docker cp "$PWD/$appfilename" "$containername":/

echo "【4】執行容器內的初始化腳本"
docker exec "$containername" sh "/$appfilename/init.sh"
複製代碼

說明:

  • 這個腳本作了這些事情:
  • 【下載mysql鏡像】:爲了防止沒有相關鏡像,因此直接下載。若是已經下載的話並無什麼影響;
  • 【經過鏡像生成容器】:這個生成過程,包括持久化設置、設置端口映射、初始化不須要密碼等;
  • 【將app文件夾拷貝到容器內】:其中 init.sh 文件是必須的,其餘根據 init.sh 文件的內容而定;
  • 【執行在容器內的 init.sh 文件】:用於初始化容器的配置;
  • 注意一件事情,當執行這裏最後一行腳本時,並不表明容器內 MySQL 服務已經徹底啓動完畢。因此在 init.sh 腳本內作了等待處理,以增長容錯性;

3.三、核心腳本:init.sh

全部在容器內,須要執行的內容,好比 SQL 腳本呀,或者是一些配置內容呀,都經過它來執行。

在這個腳本里,有如下命令:

#!/usr/bin/env bash
# 等待 MySQL 啓動完畢
echo '當前 mysql 服務狀態:'
echo `service mysql status`
echo "1.等待15秒,確保mysql已經啓動了,否則 SQL 可能沒法順利導入"
sleep 15
echo '當前 mysql 服務狀態:'
echo `service mysql status`

# 導入預建立庫表的sql文件
echo "2.開始導入數據"
mysql < /app/data.sql
echo '3.導入數據完畢.....並等待3秒.....'
sleep 3

# 因爲最開始設置mysql爲免密登錄,爲了安全,在此設置mysql密碼,並進行權限配置
echo '4.開始進行權限配置.....'
# 導入修改mysql權限設置的文件
mysql < /app/privileges.sql
echo '5.修改密碼完畢.....'

echo '----------------------------------------------------------'
echo "mysql容器啓動完畢。若是導入數據時,顯示 Can't connect to local MySQL server through socket,則說明導入失敗。容器外手動執行命令【docker exec mysql-demo sh /app/init.sh】便可"
echo '----------------------------------------------------------'
複製代碼

說明:

  • 在這個腳本里,作了這些事情:
  • 【等待 MySQL 啓動完畢】:因爲第一次啓動容器後,mysql 服務並非當即可用的(他須要必定時間來配置),所以咱們手動等待15秒時間(具體等待多久,跟服務器性能有關);
  • 【導入預建立庫表SQL】:可能咱們須要預先建立一些庫和表格,將這些sql語句寫入 data.sql 文件中;
  • 【權限管理SQL】:之因此這個SQL放到後面,是由於初始狀況咱們不須要密碼就能導入數據(啓動容器時配置的環境變量),導入這個SQL後,以後再導入sql文件就須要帳號密碼了;
  • 【通報完畢,並顯示提示信息】:告知用戶什麼狀況下是正確的情況(雖然理論上也能夠本身寫個腳本判斷輸出);
  • 【其餘】:若是你有其餘須要執行的命令,能夠在這個腳本里執行,或者寫在其餘shell文件裏,在這個腳本里執行該shell文件;

3.四、建立庫表SQL

正常狀況下, MySQL 每每須要預建立一些 database 和 table,以供程序使用,而這些最好在容器建立的時候就作到。

這裏是由 data.sql 文件來實現的。

在這個 SQL 文件裏,有如下內容:

-- 建立數據庫
DROP database IF EXISTS `docker_test_database`;
create database `docker_test_database` default character set utf8 collate utf8_general_ci;
-- 切換到test_data數據庫
use docker_test_database;
-- 建表
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
	`id` bigint(20) NOT NULL,
	`name` varchar(255) DEFAULT NULL,
	`age` bigint(20) NOT NULL,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- 插入數據
INSERT INTO `person` (`id`,`name`,`age` )
VALUES
   (0,'Tom',18);
複製代碼

說明:

  • 這個SQL文件作了如下事情:
  • 【若是有庫docker_test_database,則扔掉】:只有當須要一個新的database才須要這麼寫;
  • 【建立docker_test_database】:建立 database,並切換到這個 database;
  • 【若是有表person,則扔掉】:緣由同上面;
  • 【創建表】:建立table,並預設表結構;
  • 【插入一條測試數據】:若是插入成功,說明 MySQL 能夠正常運行;
  • 若是須要其餘sql操做,也能夠寫在這個 SQL 文件裏,或者每一個database一個sql文件,而後依次導入。

3.五、權限管理SQL

一個良好的數據庫必然會有多個不一樣權限的角色,只有這樣才能確保數據庫的安全性和穩定性。所以,咱們須要有一個權限管理SQL。

文件內容:

use mysql;
select host, user from user;
-- 任意地點的root帳號能夠用一個很是複雜的密碼登陸(瞎打的),用於禁止無密碼登陸
GRANT ALL ON *.* to root@'%' identified by 'fwefwefvvdsbwrgbr9jj24intwev0h0nbor32fwfmv1' with grant option;
-- 容許root用戶以密碼 123456 來登陸(僅限本地)
GRANT ALL ON *.* to root@'localhost' identified by '123456' with grant option;
-- 將 docker_test_database 數據庫的權限受權給建立的docker用戶,密碼爲 1234567890,但只能本機訪問(指容器內)
-- 若是用戶docker不存在,則建立用戶docker
GRANT ALL ON docker_test_database.* to docker@'localhost' IDENTIFIED by '1234567890';
-- 其餘任意地方能夠訪問,須要使用密碼 1654879wddgfg
GRANT ALL ON docker_test_database.* to docker@'%' IDENTIFIED by '1654879wddgfg';
-- mysql新設置用戶或權限後須要刷新系統權限不然可能會出現拒絕訪問:
FLUSH PRIVILEGES;
複製代碼

說明:

  • 這個腳本里作了這些事情:
  • 【切換到mysql這個庫】:這個庫負責權限管理;
  • 【查看當前用戶有哪些】:顯示當前mysql用戶;
  • 【禁止建立容器時設置的無密碼登陸】:這個是爲了安全性所實現的,密碼儘可能複雜一些,由於這個是容許遠程訪問root帳號;
  • 【容許root用戶本地登陸】:這個是本機(容器內)登陸root帳號,因此密碼能夠簡單一些。但如有實際須要,也應該寫複雜一些。
  • 【爲docker_test_database這個庫創造一個用戶】:這個用戶 docker 專門負責操做 docker_test_database 這個 database,因此權限比較低一些,容許本地訪問(有密碼);
  • 【容許docker用戶遠程訪問】:這個是爲了測試遠程能夠訪問數據庫,也能夠不容許遠程訪問(避免出現數據庫入侵);
  • 總的來講,是權限控制的一些內容。這個SQL推薦在最後執行,避免其餘SQL輸入數據時須要密碼的問題。

3.六、驗證

遠程驗證連接爲:

mysql -h [遠程主機IP地址] -P 3306 -u root -p
複製代碼

而後輸入密碼便可。

四、總結

將以上文件拷貝到主機,而後執行 create-image-mysql.sh 腳本便可。會自動安裝並配置好 MySQL。

經過以上操做,咱們實現了需求。如今,咱們再來回顧一下這個需求作了什麼事情:

  • 安裝了 MySQL 5.6 版本;
  • 持久化 MySQL 數據(將 MySQL 數據存儲到容器外);
  • 預先建立了一些 database 和 table;
  • 對 MySQL 進行了權限管理配置;

本項目資源請在個人github項目地址查看:

github.com/qq20004604/…

相關文章
相關標籤/搜索