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

概述

在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脚本,该脚本如下:

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,
  4. 将指定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

数据结果应与上述一致。

猜你喜欢

转载自blog.csdn.net/Loiterer_Y/article/details/82984549