mysql - 构建 docker 镜像时初始化数据库脚本的最佳方法

标签 mysql dockerfile

我正在使用图像“mysql”构建一个 docker 机器。我有一些安装脚本可以在第一次构建机器时运行。此设置脚本将创建一些具有指定权限的数据库和数据库用户。

以下是我文件的最小化版本..

pcdb1.entrypoint.sh

#!/bin/sh

mysql -uroot -p'pass123' -e 'show databases MYENTRYDB;'

Docker 文件

FROM mysql:5.7

COPY ./pcdb1.entrypoint.sh /
ENTRYPOINT ["/pcdb1.entrypoint.sh"];

我在日志中收到以下错误

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

pcdb1 exited with code 1

我的理解是,我的脚本试图在 mysql 启动之前运行。但我不确定如何正确地做到这一点。我可以得到建议吗?

最佳答案

编辑:20181007

我找到了您提到的问题的方法——在构建 docker 镜像时初始化数据库。但有一点不同,我发现的方式似乎是在从图像运行容器时初始化数据库,尽管在构建图像时指定了初始化脚本。

据官方information about mysql:5.7 ,有一段名为“初始化新实例”的段落。我们可以在目录/docker-entrypoint-initdb.d中添加一个初始化脚本,默认的ENTRYPOINTCMD镜像mysql:5.7将在数据库启动后执行它。

例如:

FROM mysql:5.7
COPY init-database.sql /docker-entrypoint-initdb.d/  

init-database.sql 的内容:

create database light;
create user 'light'@'%' identified by 'abc123';
grant all privileges on light.* to 'light'@'%' identified by 'abc123';
grant all privileges on light.* to 'light'@'localhost' identified by 'abc123';  

建立新形象:

docker build -t light/mysql:5.7 .  

运行一个容器:

docker run -tid --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD='abc123' light/mysql:5.7  

检查初始化:

docker run -ti mysql /bin/bash
root@25e73d40c4ff:/# mysql -uroot -p
Enter password: (abc123)
Welcome to the MySQL monitor. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;  

一切正常。

下面是以前的答案。

如何在容器中启动mysql damon?

首先,您在“尝试在启动 mysql 之前运行”部分是正确的。但是,仍然缺少“MySQL 是如何启动的”。如果你执行 docker history mysql:5.7 --no-trunc,你可以在输出中看到三个重要的记录,如下所示:

/bin/sh -c #(nop)  CMD ["mysqld"]
/bin/sh -c #(nop)  ENTRYPOINT ["docker-entrypoint.sh"]
/bin/sh -c ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh 

到目前为止我们应该知道当我们使用下面的命令启动一个mysql容器时,容器中确切的初始命令是docker-entrypoint.sh mysqld

docker run -tid -e MYSQL_ROOT_PASSWORD='abc123' mysql:5.7

如何在容器中启动mysql?

其次,现在让我们检查一下 docker-entrypoint.sh 脚本。
有一行如下所示,就在这个脚本的大致中间位置,这意味着启动 mysql 守护进程。

mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )

启动mysql后,我们可以在docker-entrypoint.sh脚本中看到很多启动语句。比如是否创建有密码的root用户,授予root权限,创建用户声明的数据库是否有MYSQL_DATABASE env等等。

以下是为您提供的解决方案。

自定义docker-entrypoint.sh脚本。

这样,你可以随心所欲地使用mysql中合法的东西。

  1. 在您的主机上获取整个 entrypoint.sh 脚本。
  2. 在脚本中加入你自定义的mysql,使你的 此脚本底部的自定义内容。我假设你 不想与原始内容混淆。
  3. 使用下面的命令和 Dockerfile 为您自己构建一个新的 mysql 镜像。

    命令:docker build -t mysql:self .
    码头文件:
    来自 mysql:5.7
    COPY/path/to/your-entrypoint.sh/
    入口点 ["/your-entrypoint.sh"]
    CMD ["mysqld"]

  4. 如果您不想要新图像,还有另一种方法可以更改 ENTRYPOINT 运行容器时。但是,您仍然应该在容器中提供您自己的脚本。
    docker run -tid -v/path/to/your-entrypoint.sh:/entrypoint.sh -p 3306:3306 -e MYSQL_ROOT_PASSWORD='abc123' mysql:5.7

使用mysql:5.7提供的默认ENV

这样,就有一个限制,尤其是你提到的“特定权限”。
您需要的 ENV 是:MYSQL_DATABASEMYSQL_USERMYSQL_PASSWORD
命令应该是这样的:

docker run -tid -e MYSQL_ROOT_PASSWORD='abc123' -e MYSQL_DATABASE='apps' -e MYSQL_USER='light' -e MYSQL_PASSWORD='abc123' mysql:5.7 

这意味着数据库 apps 和用户 light 将被自动创建,用户 light 将被授予数据库的 super 用户权限应用

更多引用here在 hub.docker.com 上。

关于mysql - 构建 docker 镜像时初始化数据库脚本的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52535725/

相关文章:

postgresql - 如果 ENTRYPOINT 未完成,Dockerfile 不会运行 CMD

mysql - 我应该将组织表分成两个表吗?

mysql - 与相关产品表中相同型号的产品

mySQL Schema 设计建议

docker - 如何使用 Docker 文件将一层中的多个文件复制到不同的位置?

docker - 在从 Dockerfile 进行 docker 构建期间使用 STDIN

python - views.py 和 urls.py 不连接来执行功能

mysql选择数据并在2个表之间进行计算并按月分组

docker - 如何从 Dockerfile 上的父镜像中删除入口点

mongodb - Bluemix IBM Container 与 Mongodb 连接失败