【问题标题】:How to run a query in docker container after mariadb has started?mariadb启动后如何在docker容器中运行查询?
【发布时间】:2021-05-24 17:15:41
【问题描述】:

我正在尝试创建一个 mariadb 容器,并希望在开头启动一个 SQL 脚本。

基础 Dockerfile

FROM mariadb:10.5.6
# Copy a "creation.sql" script to the container
COPY /sql/* /sql/

手动执行作品

如果我在容器启动后等待 10-20 秒,然后执行命令行 docker exec -it my_container_name mysql -e "source sql/creation.sql;" -uroot -pMyPasswordHere 然后脚本运行正常。但我宁愿这部分的构建或运行过程,而不是需要手动步骤和猜测等待时间。

运行 - 不起作用

我尝试在 Dockerfile 中使用 RUN

RUN mysql -e "source sql/creation.sql;" -uroot -p$MYSQL_ROOT_PASSWORD`

但它 失败:在构建期间无法通过套接字连接到本地 MySQL 服务器。我认为这是因为服务尚未启动。

CMD - 不起作用

我还尝试使用ENTRYPOINTCMD 使用mysql 执行creation.sql,但它们在运行期间似乎失败了。应调用mysqld(匹配mariadb Dockerfile 中的内容)然后运行sql,但在运行容器时失败的CMD 解决方案示例:

FROM mariadb:10.5.6
COPY /sql/* /sql/
CMD mysqld && mysql -e "source sql/creation.sql;" -uroot -p$MYSQL_ROOT_PASSWORD

带有 shell 脚本的 CMD - 不起作用

同样失败的基于脚本的解决方案示例:

FROM mariadb:10.5.6
COPY /sql/* /sql/
COPY /scripts/* /scripts/
CMD ["./scripts/start.sh"]

start.sh:

exec mysqld
echo "Running start script\n" > start.log
for i in {1..20}
do
    sleep 3
    echo "Attempt $i"
    echo "Attempt $i" &>> start.log
    mysql -e "source sql/creation.sql;" -uroot -p$MYSQL_ROOT_PASSWORD &>> start.log
done
echo "Done" &>> start.log

有简单的解决方案吗?

有没有什么方法可以只用 Dockerfile 或者一个小的 shell 脚本来运行 SQL 脚本文件?

【问题讨论】:

标签: mysql docker mariadb


【解决方案1】:

您可以将命令添加为 CMD 行:

FROM mariadb:10.5.6

# Copy a "creation.sql" script to the container
COPY /sql/* /sql/

CMD mysql -e "source sql/creation.sql;" -uroot -pMyPasswordHere

您也可以从 docker-compose.yml 文件中调用 CMD:

version: '3'
services:
  service:
    ...
    command: 'command-to-start'

您可能需要在其中添加一行以使其休眠一段时间,以确保在脚本运行之前进程可以正常启动。您可以将其放入脚本中,但如果需要,可以将其作为第一个命令包含在 CMD 行中,然后是您的脚本:CMD first-command-to-sleep && second-command

如果您发现 CMD 选项阻止 MariaDB 启动,您可能需要添加自己的请求以启动该进程。查看他们的 Dockerfile (https://github.com/MariaDB/mariadb-docker/blob/master/10.5/Dockerfile) 表明它是:

CMD ["mysqld"]

所以你会有CMD first-command & second-command & mysqld

& 将使两者同时运行,而&& 将等待第一个成功完成后再运行:Can a bash script run simultaneous commands then wait for them to complete?

这将作为一个 shell 进程执行,而不是 exec,它有一些缺点:https://til.codes/docker-run-vs-cmd-vs-entrypoint/

其他选项包括将所有内容放入 shell 脚本,并在启动时调用它:CMD ["start.sh"]。在这里,您将确保最后一个命令 mysqld 以exec mysqld 执行,然后确保它是执行的主进程,就像运行CMD ["mysqld"]

如果您想制作自己的服务容器,也可以使用像 SupervisorD 这样的服务:http://supervisord.org

或者给每个进程一个自己的容器。不理会标准的 MariaDB 容器,然后运行带有脚本的容器来调用命令或执行自定义进程。当然,这完全取决于您要尝试做什么以及您需要与容器内容进行多少交互。如果调用 docker 容器命令,您可以将 docker 套接字安装到您的容器中,安装 docker,然后能够在其中执行 docker exec -it my_container_name mysql -e "source sql/creation.sql;" -uroot -pMyPasswordHere 命令:Access Docker socket within container。如果您发现需要构建一个在您的应用中执行大量自定义流程的主管容器,这可能是一个不错的选择。

与往常一样,有很多方法可以解决这个问题。我会先尝试:

CMD mysql -e "source sql/creation.sql;" -uroot -pMyPasswordHere

如果 mariadb 没有启动是因为它覆盖了默认的 CMD 进程,那么可能会探索 start.sh 解决方案。

我对 MariaDB 不熟悉,但我也会探索您尝试运行的命令是否可以作为配置文件传递或附加到启动命令:mysqld --variable --etc.:https://hub.docker.com/_/mariadb/

【讨论】:

  • 优秀而深入的答案......但不幸的是我没有运气。我尝试了CMD 使用带有循环和睡眠的脚本,使用&& 的各种命令等。CMD 的任何错误似乎都会默默地停止容器,我相信运行mysqld 存在权限问题。像 Docker 套接字和 SupervisorD 这样的东西现在对我来说太深了。
  • 您能否分享您选择的方法的完整代码,以便我们尝试复制它?
  • 我在对原始问题的尝试中添加了更多详细信息
  • CMD mysqld && mysql -e "source sql/creation.sql;" -uroot -p$MYSQL_ROOT_PASSWORD
  • 在 shell 脚本中, exec mysqld 可能会阻止脚本的其余部分运行。您需要同时运行命令:stackoverflow.com/questions/3004811/…
【解决方案2】:

查看 Docker Hub 上的 MariaDB 文档,似乎内置了一个用于执行辅助脚本的进程:

当一个容器第一次启动时,一个新的数据库 将使用提供的创建和初始化指定的名称 配置变量。此外,它将执行文件 扩展名 .sh、.sql、.sql.gz 和 .sql.xz /docker-entrypoint-initdb.d。文件将按字母顺序执行 命令。没有文件执行权限的 .sh 文件的来源,而不是 比执行。您可以通过以下方式轻松填充 mariadb 服务 将 SQL 转储安装到该目录并提供自定义图像 贡献的数据。 SQL 文件将默认导入到 由 MARIADB_DATABASE / MYSQL_DATABASE 变量指定的数据库。

https://hub.docker.com/_/mariadb

【讨论】:

    猜你喜欢
    • 2018-05-20
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2022-07-18
    • 2014-11-04
    • 2018-05-16
    • 2020-07-17
    • 2019-04-22
    相关资源
    最近更新 更多