我试图使用docker(-compose)使我的开发过程更容易/可维护。 我不想使用任何卷(如果可能的话)。 为什么在运行' docker-compose up -d'后,import.sh无法执行?
我有以下文件:
docker-compose.yml
mysql
---- import.sh
---- db.sql
---- Dockerfile
在 docker-compose.yml 中有:
version: '2'
services:
database:
image: mysql
build:
context: ./mysql/
dockerfile: Dockerfile
container_name: mysqltest
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
/ mysql / Dockerfile 中的有:
ADD import.sh /tmp/import.sh
ADD db.sql /tmp/db.sql
RUN /tmp/import.sh
/mysql/db.sql 中的有:
CREATE DATABASE test1;
CREATE DATABASE test2;
CREATE DATABASE test3;
答案 0 :(得分:19)
您可以在Dockerfile中使用ENTRYPOINT
或CMD
来在容器启动时执行命令。它们之间的区别在于,ENTRYPOINT
在容器启动时执行,而CMD
可能会被命令行选项替换。假设您要执行的命令是X
docker run my-image Y
如果X
在Dockerfile中,将执行ENTRYPOINT X
,如果Y
在Dockerfile中,则CMD X
将执行。
但是,有两点需要注意:
因此,典型的解决方案是使用docker-entrypoint
脚本。它检查它是否在启动其环境的新容器中运行,然后执行容器的实际程序。
看一下official mysql Dockerfile and entrypoint以获得一个想法。
示例入口点脚本可能如下所示:
$ cat docker_entrypoint.sh
if [ ! -f .initialized ]; then
echo "Initializing container"
# run initializing commands
touch .initialized
fi
exec "$@"
首先,它会检查是否存在名为.initialized
的文件。如果没有,则运行一些命令来初始化容器环境。之后touch .initialized
创建.initialized
作为空文件。因此,后续容器启动将不会再次执行初始化命令。
其次,它开始实际的服务。使用exec
执行此操作将使用服务的进程替换shell进程。因此,docker将保持容器运行,直到服务终止。 "$@"
将包含“container / image命令”。这在Dockerfile中设置为CMD X
,并且在命令上被覆盖,正如我上面已经指出的那样。通过使用exec "$@"
,您将能够在容器中启动不同的程序以进行检查,例如bash
,默认启动服务,如Dockerfile的CMD
语句中所指定。
答案 1 :(得分:0)
如果您只是想在第一次初始化数据库,可以使用这种简单方法。
volumes:
- [the scripts dir]:/docker-entrypoint-initdb.d
初始化一个新实例 首次启动容器时,将创建一个具有指定名称的新数据库,并使用提供的配置变量对其进行初始化。此外,它将执行在/docker-entrypoint-initdb.d中找到的扩展名为.sh,.sql和.sql.gz的文件。文件将按字母顺序执行。您可以通过将SQL转储安装到该目录中并为自定义图像提供贡献的数据来轻松填充mysql服务。默认情况下,SQL文件将导入到MYSQL_DATABASE变量指定的数据库中。