Docker Hub MySQL官方镜像实现首次启动后初始化库表

Author Avatar
子语 2017 - 09 - 29
  • 在其它设备中阅读本文章

概述

在Docker Hub中查看MySQL官方镜像的Dockerfile:


COPY docker-entrypoint.sh /usr/local/bin/

RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat

ENTRYPOINT ["docker-entrypoint.sh"]

镜像启动时,会运行entrypoint.sh脚本,该脚本的shell命令中:

echo
    for f in /docker-entrypoint-initdb.d/*; do
		case "$f" in
			*.sh)     echo "$0: running $f"; . "$f" ;;
			*.sql)    echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
			*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
			*)        echo "$0: ignoring $f" ;;
		esac
		echo
done

上述shell命令会遍历/docker-entrypoint-initdb.d/文件中的sh文件,sql文件,sql.gz压缩包,随后按照sh>sql>sql.gz的顺序依次执行。当该文件夹只存在一种文件时,便会按照文件名排序后执行。

实现首次启动后初始化库表

创建mysql_data文件夹,将data.sql放入:

-- 创建数据库 
DROP database IF EXISTS `docker_database`;
create database `docker_database` default character set utf8 collate utf8_general_ci; 
-- 切换到test_data数据库
use docker_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 `user` (`id`,`name`,`age` ) 
VALUES 
   (0,'Tom',18);

启动容器

$ docker run --name test -v /home/master/mysql_data:/docker-entrypoint-initdb.d -d -e MYSQL_ROOT_PASSWORD=123456  mysql 

进入容器进行验证

$ docker exec -it sql /bin/bash
root@6da21b87a0a5:/# mysql -u root -p 
Enter password:
mysql> use docker_database;
mysql> show tables;
+---------------------------+
| Tables_in_docker_database |
+---------------------------+
| person                    |
+---------------------------+
1 row in set (0.00 sec)
mysql> select * from person;
+----+------+------+
| id | name | age  |
+----+------+------+
|  0 | Tom  |   18 |
+----+------+------+
1 row in set (0.00 sec)
mysql> insert into person(id ,name ,age)values(1,'Jane',17);
Query OK, 1 row affected (0.06 sec)
mysql> select * from person;                                
+----+------+------+
| id | name | age  |
+----+------+------+
|  0 | Tom  |   18 |
|  1 | Jane |   17 |
+----+------+------+
2 rows in set (0.00 sec)

重启该容器后,数据依然存在。但启动一个新容器后,该容器数据依然为初始状态。

指定sql文件运行顺序

entrypoint.sh脚本执行sql文件的顺序是按照文件名排序的,这可能导致一些文件执行顺序不符合预期,从而出现错误。例如预期是数据库创建后,再执行表格创建,最后插入数据,而因为文件名,可能数据库先创建后,插入数据,最后创建表格,从而使得数据插入失败。要解决该问题有如下几种方法:

  1. 将文件按照预期顺序,进行命名,比如1_xx,2_xx;
  2. 将必须有前后顺序的sql文件合并在一个sql文件中;
  3. 将sql文件单独放在一个文件夹如data_mysql,将指定sql文件执行顺序的shell脚本放在shell_mysql文件中。容器启动时,将shell_mysql映射到docker-entrypoint-initdb.d文件夹,data_mysql映射到容器内其他文件夹。
    假设:data_mysql文件夹存放三个sql文件: database.sql,table.sql,data.sql,shell_mysql存放data.sh
#!/bin/bash
mysql -uroot -p$MYSQL_ROOT_PASSWORD <<EOF
source /usr/local/work/database.sql;
source /usr/local/work/table.sql;
source /usr/local/work/data.sql; 

启动容器:

$ docker run --name test -e WORK_PATH=/usr/local/work -e MYSQL_ROOT_PASSWORD=123456 -v /home/master/shell_mysql:/docker-entrypoint-initdb.d -v /home/master/data_mysql:/usr/local/work mysql

数据结果应与上述一致。

This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接:http://yov.oschina.io/article/容器/Docker/Docker Hub MySQL官方镜像实现首次启动后初始化库表/