1. 前言
Docker在開發中使用的越來越多了,最近搞了一個Spring Boot應用,為了方便部署將Mysql也放在Docker中執行。那麼怎麼初始化 SQL指令碼以及資料呢?
我這裡有兩個傳統方案。 第一種方案是在容器啟動後手動匯入,太low了不行。第二種在Spring Boot客戶端連線Mysql容器時初始化資料庫,你可以參考使用flyway進行資料庫版本控制一文,但是這依賴客戶端的能力。能不能做到Mysql容器啟動時就自己初始化資料庫呢?當然可以!今天就來演示一下。全部程式碼見文末。
2.原理
當Mysql容器首次啟動時,會在 /docker-entrypoint-initdb.d
目錄下掃描 .sh
,.sql
,.sql.gz
型別的檔案。如果這些型別的檔案存在,將執行它們來初始化一個資料庫。這些檔案會按照字母的順序執行。預設情況下它們會初始化在啟動容器時宣告的 MYSQL_DATABASE
變數定義的資料庫中,例如下面的命令會初始化一個REGION_DB
資料庫:
$ docker run --name some-mysql -e MYSQL_DATABASE=REGION_DB -d mysql:tag
如果你的啟動命令沒有指定資料庫那麼就必須在資料庫DDL指令碼中宣告並指定使用該資料庫。否則就會實現下面的異常:
ERROR 1046 (3D000) at line 7: No database selected
那麼接下來我們將利用這一機制來實現Docker容器啟動時初始化資料庫。
3.自定義Dockerfile
我們編寫自己的Dockerfile來實現我們的需求,這裡以 Mysql:5.7 為例。不同的版本可能有一定的出入,需要詳細去閱讀官方文件。指令碼如下:
FROM mysql:5.7
LABEL OG=felord.cn
COPY utf8mb4.cnf /etc/mysql/conf.d/utf8mb4.cnf
COPY ./sql /tmp/sql
RUN mv /tmp/sql/*.sql /docker-entrypoint-initdb.d
RUN rm -rf /tmp/sql
- 第一步,引入官方 Mysql:5.7 Docker映象。
- 第二步,無實際意義,主要是作者、組織資訊。
- 第三步,很重要!本來我沒有配置第三行,結果執行容器後發現初始化資料的中文全部亂碼了。所以需要在初始化資料庫前修改Mysql的編碼等配置,這裡我順便把時區也改為了
+8:00
。 - 第四步,複製包含資料庫指令碼的
./sql
資料夾到映象的/tmp/sql
下。 - 第五步,使用
mv
命令把第四步拷貝的資料夾下的所有.sql
檔案複製到/docker-entrypoint-initdb.d
下,這樣才能利用2.章節的機制進行初始化資料庫。 - 第六步,刪除使用過的臨時目錄。
然後你可以通過構建映象命令構建自定義的Mysql映象:
# 一定不要忘記最後的一個 . 點
docker build -t mysql:5.7c .
通過mysql:5.7c
映象啟動一個名稱為mysql-service
的容器,root密碼為123456
,並持久化資料到宿主機 D:/mysql/data
下:
docker run --name mysql-service -v d:/mysql/data:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7c
小貼士:你可以通過
SHOW VARIABLES LIKE 'character%'
檢視字符集是否更改為utf8mb4
,也可以通過SHOW VARIABLES LIKE '%time_zone%'
檢視時區是否是東八區。
4. 總結
今天我們自定義一個可以執行初始化資料庫的Mysql映象,方便我們進行部署。你也可以參考這個思路來定製其它一些自己需要的Docker映象。本文的完整Demo可通過我個人部落格獲取。
關注公眾號:Felordcn 獲取更多資訊