我有一个Makefile来启动运行MySql的Docker容器。 我想运行我的setup.sql文件来设置数据库,但是我一直显示“不是这样的文件或目录”。 这是我的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)
给我带来麻烦的命令是:
make setup
make create_tables
他们两个都给我“没有这样的文件或目录”。 即使我从Makefile外部运行它们。
答案 0 :(得分:1)
可能最简单的方法是在包含两个.sql
文件的主机上创建一个目录,并在启动时将其绑定安装到Docker容器中。如果持久性存储中没有数据库,则容器在创建数据库时将自动运行它们。请参阅mysql image documentation中的“初始化新实例”。
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)
如果不能这样做,则可以在主机上运行普通的MySQL客户端。这避免了容器具有自己的文件系统周围的若干问题,有效地需要以root用户身份运行docker
命令,以及避免shell引用问题。 (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) < $<
如果必须使用docker exec
,请记住,在将控制权移交给Docker之前,shell重定向发生了:如果您docker exec ... < file
您的本地shell打开了{{1} }在主机上进行读取,并成为运行命令file
的标准输入。在您的示例中,您的shell命令正在从主机上的docker exec
进行读取,并且会产生“找不到文件”错误。