我有一个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外部运行它们。
可能最直接的方法是在主机上创建一个包含两个.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
,那么请记住shell重定向在控制交给Docker之前发生:如果你docker exec ... < file
你的本地shell在主机上打开file
进行读取,那将成为命令docker exec
运行的标准输入。在你的例子中,你的shell命令是从主机上的/tmp/setup.sql
读取,并且产生“找不到文件”错误。