简体   繁体   English

使用Makefile在Docker容器中运行SQL脚本

[英]Run SQL script inside Docker container with Makefile

I have a Makefile to start a Docker Container running MySql. 我有一个Makefile来启动运行MySql的Docker容器。 I want to run my setup.sql file to setup my database but I keep having "Not such file or directory". 我想运行我的setup.sql文件来设置数据库,但是我一直显示“不是这样的文件或目录”。 Here is my Makefile: 这是我的Makefile:

CONTAINER = NETFLIX

#DOCKER CONTAINER RELATED
NAME = --name $(CONTAINER)
PASS = -e MYSQL_ROOT_PASSWORD=secret mysql:5.7
CHARSET = --character-set-server=utf8mb4
COLLATION = --character-set-server=utf8mb4

create:
    docker run -d -p 33061:3306 $(NAME) $(PASS) $(CHARSET) $(COLLATION)

start:
    docker start $(CONTAINER)

stop:
    docker stop $(CONTAINER)

remove: stop 
    docker rm $(CONTAINER)

reset_hard: stop remove create start

reset: stop start

#DATABASE RELATED (build, create, populate DB)

define run_script
    docker cp $(1) $(CONTAINER):/tmp/
    docker exec -it $(CONTAINER) mysql -u root -psecret < /tmp/$(1)
    echo "$(cat $(1))"
endef

setup:
    $(call run_script,setup.sql)

create_tables:
    $(call run_script,create_tables.sql)

Commands giving me troubles are: 给我带来麻烦的命令是:

make setup
make create_tables

Both of them give me "No such File or Directory". 他们俩都给我“没有这样的文件或目录”。 Even if I run them from outside the Makefile. 即使我从Makefile外部运行它们。

Possibly the most straightforward way to do this is to create a directory on the host containing the two .sql files and bind-mount it into the Docker container when it starts. 可能最简单的方法是在包含两个.sql文件的主机上创建一个目录,并在启动时将其绑定安装到Docker容器中。 If there isn't already a database in persistent storage, then the container will run them automatically when it creates the database. 如果持久性存储中没有数据库,则容器在创建数据库时将自动运行它们。 See "Initializing a fresh instance" in the mysql image documentation . 参见mysql镜像文档中的“初始化一个新实例”。

MYSQL_PORT := 33061
MYSQL_ROOT_PASSWORD := secret
PORTS := -p $(MYSQL_PORT):3306
VOLUMES := -v $(PWD)/scripts:/docker-entrypoint-initdb.d
ENVS := -e MYSQL_ROOT_PASSWORD=$(MYSQL_ROOT_PASSWORD)
IMAGE := mysql:5.7
RUN_OPTS := $(PORTS) $(VOLUMES) $(ENVS)
ARGS := --character-set-server=utf8mb4

run:
        docker run -d $(RUN_OPTS) $(IMAGE) $(ARGS)

If you can't do that, then you can run an ordinary MySQL client on the host. 如果不能这样做,则可以在主机上运行普通的MySQL客户端。 This avoids several issues around the container having its own filesystem, effectively needing to be root to run docker commands, and shell quoting issues. 这避免了容器具有自己的文件系统周围的多个问题,有效地需要以root用户身份运行docker命令以及shell引用问题。 ( docker exec probably shouldn't be part of your core workflow.) docker exec可能不应该成为您核心工作流程的一部分。)

setup: setup.sql
        mysql -h localhost -P $(MYSQL_PORT) -w -u root -p $(MYSQL_ROOT_PASSWORD) < $<
create_tables: create_tables.sql
        mysql -h localhost -P $(MYSQL_PORT) -w -u root -p $(MYSQL_ROOT_PASSWORD) < $<

If you must use docker exec , then remember that shell redirection happens before control gets handed over to Docker land: if you docker exec ... < file your local shell opens file on the host for reading and that becomes the standard input to the command docker exec runs. 如果必须使用docker exec ,那么请记住,shell重定向是控制权移交给Docker land 之前发生的:如果docker exec ... < file本地shell会在主机上打开file以供读取,并且成为命令的标准输入docker exec运行。 In you're example your shell command is reading from /tmp/setup.sql on the host and that's producing the "file not found" error. 在您的示例中,您的shell命令正在从/tmp/setup.sql上的/tmp/setup.sql读取,并且正在产生“找不到文件”错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM