在docker 創建 mysql 容器時,往往需要在創建容器的過程中創建database 實例,代碼如下:
docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=my_db mysql:latest
MYSQL_ROOT_PASSWORD=123456,指定 root 用戶名密碼 123456
MYSQL_DATABASE=my_db 創建數據庫實例 my_db
但有時我們還希望在創建實例的過程中初始化我們的sql腳本,mysql的官方鏡像可以支持在容器啟動的時候自動執行指定的sql腳本或者shell腳本,我們一起來看看mysql官方鏡像的Dockerfile,如下圖:
已經設定了ENTRYPOINT,里面會調用/entrypoint.sh這個腳本,腳本其中一段內容如下圖:
遍歷docker-entrypoint-initdb.d目錄下所有的.sh和.sql后綴的文件并執行。
原理清楚了,那我們就開始動手操作,思路是將數據庫初始化腳本拷貝到docker-entrypoint-initdb.d 目錄下,編寫Dockerfile 文件,內容如下:
fileName: Dockerfile
#基礎鏡像使用 mysql:latest
FROM mysql:latest
#作者
MAINTAINER gjaxx <gjaxx@sohu.com>
#定義會被容器自動執行的目錄
ENV AUTO_RUN_DIR /docker-entrypoint-initdb.d
#定義初始化sql文件
ENV INSTALL_DB_SQL init_database.sql
#把要執行的sql文件放到/docker-entrypoint-initdb.d/目錄下,容器會自動執行這個sql
COPY ./$INSTALL_DB_SQL $AUTO_RUN_DIR/
#給執行文件增加可執行權限
RUN chmod a+x $AUTO_RUN_DIR/$INSTALL_DB_SQL
fileName: init_database.sql
-- 建庫
CREATE DATABASE IF NOT EXISTS my_db default charset utf8 COLLATE utf8_general_ci;
-- 切換數據庫
use my_db;
-- 建表
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年齡',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 插入數據
INSERT INTO `table1` (`id`, `name`, `age`)
VALUES
(1,'姓名1',10),
(2,'姓名2',11);
生成鏡像
docker build -t init_mysql:0.0.1 .
“init_mysql:0.0.1”為鏡像名稱,“.” 表示Dockerfile在當前路徑下,可以通過
docker images
命令查看本地鏡像,結果如下:
根據鏡像生成容器
docker run --name mysql -p 12345:3306 -e MYSQL_ROOT_PASSWORD=123456 -d init_mysql:0.0.1
“--name mysql” 指定容器名字,“-p 12345:3306”指定容器暴漏的端口號,“init_mysql:0.0.1” 鏡像名稱,通過
docker ps
命令查看運行中的容器,如下:
可以通過
docker exec -it CONTAINERID bin/bash
命令,進入運行中容器查看初始化腳本是否成功,其中“CONTAINERID” 為容器ID,進入容器后登錄mysql,可以看到my_db 已存在,table1已創建,表中已有初始化數據
mysql -uroot -p123456;
show databases;
use my_db;
select * from table1;
但以上方式有個問題,就是如果有多個sql文件,無法保證執行順序,這就需要引入 sh 文件,思路是在docker-entrypoint-initdb.d 目錄下放置 sh 文件,在 sh 文件中依次執行 sql 文件,編寫Dockerfile、install_db.sh、init_database.sql、init_table.sql、init_data.sql 文件,內容如下:
fileName: Dockerfile
#基礎鏡像使用 mysql:latest
FROM mysql:latest
#作者
MAINTAINER gjaxx <gjaxx@sohu.com>
#定義工作目錄
ENV WORK_PATH /usr/local/work
#定義會被容器自動執行的目錄
ENV AUTO_RUN_DIR /docker-entrypoint-initdb.d
#定義sql文件名
ENV FILE_0 init_database.sql
ENV FILE_1 init_table.sql
ENV FILE_2 init_data.sql
#定義shell文件名
ENV INSTALL_DB_SHELL install_db.sh
#創建文件夾
RUN mkdir -p $WORK_PATH
#把數據庫初始化數據的文件復制到工作目錄下
COPY ./$FILE_0 $WORK_PATH/
COPY ./$FILE_1 $WORK_PATH/
COPY ./$FILE_2 $WORK_PATH/
#把要執行的shell文件放到/docker-entrypoint-initdb.d/目錄下,容器會自動執行這個shell
COPY ./$INSTALL_DB_SHELL $AUTO_RUN_DIR/
#給執行文件增加可執行權限
RUN chmod a+x $AUTO_RUN_DIR/$INSTALL_DB_SHELL
fileName:install_db.sh
mysql -uroot -p$MYSQL_ROOT_PASSWORD << EOF
source $WORK_PATH/$FILE_0;
source $WORK_PATH/$FILE_1;
source $WORK_PATH/$FILE_2;
fileName:init_database.sql
CREATE DATABASE IF NOT EXISTS my_db default charset utf8 COLLATE utf8_general_ci;
fileName:init_table.sql
use my_db;
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年齡',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
fileName:init_data.sql
use my_db;
INSERT INTO `table1` (`id`, `name`, `age`)
VALUES
(1,'姓名1',10),
(2,'姓名2',11);
生成鏡像和容器代碼如上,這里就不重復了。