創建MySQL容器的教程有很多,搜了一大堆都是使用-v映射自己的配置文件和數據文件,而且都是指定的原先容器內的MySQL默認數據存儲路徑,但公司一般都會將數據文件、binglog、redolog、slowlog、errlog等文件分類存儲,放在自己定義的路徑下。本篇博客就講一下如何加載外部自定義配置文件,並將數據庫運行的數據分類持久化到宿主機。
本篇博客基於docker run -v的一個特性:如果映射的目錄在容器內不存在,那麼就會自動在容器內創建。最終達到的效果就是可以隨時根據自己的配置文件啓動MySQL容器,且產生的數據和日誌文件都持久化在宿主機,不會丟失。
理論部分:
首先看一下我規劃的宿主機和容器內的目錄結構(見下面的圖,畫了好久)。通過宿主機的目錄簡單講下各個文件夾的意思
1)3306文件夾下存放3306端口的MySQL實例(如果有3307實例,那就新建3307文件夾進行存放,以此類推。。。。)
2)data存放數據文件,就是一些idb、frm文件。
3)errlog存放數據庫運行的日誌,如果MySQL有報錯那就去這裏看。
4)logdir文件夾下是binglog和redolog兩個文件夾。
5)slowlog文件夾是存放慢日誌。
6)tmpdir文件夾是數據庫臨時文件。
7)mysqld.pid和mysql.sock是數據庫運行時產生的文件,數據庫停止就會消失。(名字命名可能有些差異)
8)conf文件夾是MySQL的配置文件my.cnf(Windows下是my.ini)
宿主機的這些文件夾和容器文件夾的映射關係通過下面的圖就能看明白。
實踐部分:
環境:Centos7.3 、MariaDB10.1.13鏡像、my.cnf文件
我的配置文件中和路徑相關的參數如下:
# 這個是MySQL容器默認的數據庫安裝路徑
basedir = /usr
socket = /mysqldata/3306/data/discard/other/mysql.sock
pid-file = /mysqldata/3306/data/discard/other/mysqld.pid
# 數據
datadir = /mysqldata/3306/data
# 錯誤日誌
log-error = /mysqldata/3306/data/discard/errlog/mysqld.err
# 這個缺省爲datadir,可不寫
innodb_data_home_dir = /mysqldata/3306/data
# binlog
log-bin=/mysqldata/3306/discard/data/logdir/binlog/binlog
# redolog
innodb_log_group_home_dir = /mysqldata/3306/data/discard/logdir/redolog
# 臨時文件
tmpdir=/mysqldata/3306/data/discard/tmpdir
#慢查詢日誌
slow_query_log_file='/mysqldata/3306/data/discard/slowlog/slow.log'
步驟:
一、在宿主機上創建數據目錄(後來發現個坑,要給conf文件夾賦權755,我也不知道爲啥)
mkdir -p /mysqldata/3306/data
mkdir -p /mysqldata/3306/logdir/binlog
mkdir -p /mysqldata/3306/logdir/redolog
mkdir -p /mysqldata/3306/errlog
mkdir -p /mysqldata/3306/tmpdir
mkdir -p /mysqldata/3306/slowlog
mkdir -p /mysqldata/3306/conf
chmod -R 755 /mysqldata/3306/conf
二、拉取鏡像
docker pull mariadb:10.1.13(這裏填自己公司的鏡像路徑或者外網的倉庫地址)
檢查下有沒有
docker image ls | grep mariadb
三、啓動容器
啓動容器,鏡像名和第二步鏡像名稱一致
(啓動後,宿主機的/mysqldata/3306/data下會出現空的discard文件夾,可以刪除。但每次重啓容器就會產生)
docker run -d --name mysql3306 -e MYSQL_ROOT_PASSWORD=123456 --net=host \
-v /mysqldata/3306/data:/mysqldata/3306/data \
-v /mysqldata/3306/errlog:/mysqldata/3306/data/discard/errlog \
-v /mysqldata/3306/logdir/binlog:/mysqldata/3306/data/discard/logdir/binlog \
-v /mysqldata/3306/logdir/redolog:/mysqldata/3306/data/discard/logdir/redolog \
-v /mysqldata/3306/tmpdir:/mysqldata/3306/data/discard/tmpdir \
-v /mysqldata/3306/slowlog:/mysqldata/3306/data/discard/slowlog \
-v /mysqldata/3306:/mysqldata/3306/data/discard/other \
-v /mysqldata/3306/conf:/etc/mysql/conf.d \
--privileged=true mariadb:10.1.13
參數解釋:
1)name 指定要創建的容器名
2)-e 指定MySQL用戶的密碼
3)--net是網絡模式,這裏用的host模式,即和宿主機共用一個網絡命名空間,其實就是使用宿主機的IP和端口。也可以使用
-p 3306:3306這種方式來映射端口,但是它倆不能一起使用哦。
4)-v 地址映射。冒汗前是宿主機目錄,冒號後是對應的容器內目錄(如果該目錄不存在,會自動創建)。映射關係就像圖中畫的一樣,大家仔細對應一下,最後一個之所以要將conf文件夾映射到/etc/mysql/conf.d下,是因爲官方文檔說:將含有.cnf文件結尾的文件夾映射到這個文件夾下後,在啓動MySQL容器的時候,會自動使用我們的配置文件來替換原來的。文檔地址:https://hub.docker.com/_/mariadb。我把那段話截出來了:
5)--privileged=true 容器內的root擁有真正root權限,否則容器內root只是外部普通用戶權限
四、查看鏡像狀態及日誌(多種方式)
docker ps -a | grep mysql3306
docker logs mysql3306
docker inspect mysql3306
五、查看啓動的端口占用情況
netstat -tunl|grep 3306
六、修改容器爲自啓動(根據自己的需求可改可不改)
docker container update --restart=always mysql3306
七、進入鏡像
docker exec -it mysql3306 bash
八、測試連接mysql(或者在外部用Navicate連接)
mysql -uroot -p
部分解釋:
1、爲什麼不將errlog/slowlog/logdir/tmpdir等放在和data目錄同級,和宿主機一樣,多方便。
我一開始也是這麼想的,但是發現容器創建的這幾個文件夾的時候,只會將數據文件夾賦用戶組mysql:mysql,其它幾個文件夾都是一堆亂七八糟的用戶組,導致啓動容器的時候沒有權限讀取這幾個文件夾下的內容,從而啓動失敗。
具體可以通過 docker inspect 容器名 這個命令查如下的參數
"Config": {
......
"Entrypoint": [
"/docker-entrypoint.sh"
],
......
}
這個是容器的入口函數,即容器啓動後會自動執行/docker-entrypoint.sh這個腳本。
通過查看該腳本,發現它僅把數據庫數據文件夾(data)賦予了mysql:mysql用戶組。
2、爲什麼還要在data下加一個discard目錄?
也可以不加,直接放在data目錄下。但是當你連接mysql後,用 show databases; 看一下(或者Navicate看一下),會發現多出來了errlog/slowlog/logdir/tmpdir這幾個數據庫,MySQL把data下的文件夾都當成了數據庫。所以爲了美觀,我就加了層discard目錄。
第一次寫關於數據庫的文章,呼,寫了一個多小時,歡迎大佬們批評指正。