MySQL docker-compose up 后如何执行脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42117362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 22:11:39  来源:igfitidea点击:

How to execute scripts after docker-compose up?

mysqldockerdocker-compose

提问by p0rter

I'm trying to make my dev process easier/maintainable using docker(-compose). I do not want to use any volumes (if that's possible). Why does import.sh not get executed after I run 'docker-compose up -d'?

我正在尝试使用 docker(-compose) 使我的开发过程更容易/可维护。我不想使用任何卷(如果可能的话)。为什么在我运行 'docker-compose up -d' 后没有执行 import.sh?

I have the following files:

我有以下文件:

docker-compose.yml
  mysql
  ---- import.sh
  ---- db.sql
  ---- Dockerfile

in docker-compose.ymlthere is:

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

in /mysql/Dockerfilethere is:

/mysql/Dockerfile 中有:

ADD import.sh /tmp/import.sh
ADD db.sql /tmp/db.sql
RUN /tmp/import.sh

in /mysql/db.sqlthere is:

/mysql/db.sql 中有:

CREATE DATABASE test1;
CREATE DATABASE test2;
CREATE DATABASE test3;

回答by fzgregor

You can use ENTRYPOINTor CMDin your Dockerfile to execute a command when the container starts. The difference between them is that ENTRYPOINTis executed any time the container is started, while CMDmight be replaced with an command line option. Assuming the command you want to execute is X

您可以在 Dockerfile 中使用ENTRYPOINTCMD在容器启动时执行命令。它们之间的区别是ENTRYPOINT在容器启动时执行,而CMD可能会被命令行选项替换。假设您要执行的命令是X

docker run my-image Y

will execute Xif ENTRYPOINT Xwas in the Dockerfile and Yif CMD Xwas in the Dockerfile.

X如果ENTRYPOINT X在 Dockerfile 中,Y如果CMD X在Dockerfile 中,将执行。

However, there are two caveats:

但是,有两个警告:

  1. The command will be executed every time the container is started.
  2. After the command terminates the container is shut down.
  1. 每次启动容器时都会执行该命令。
  2. 命令终止后,容器将关闭。

Therefore, a typical solution is to have a docker-entrypointscript. It checks whether it is run in a fresh container initiating its environment and afterwards executes the container's actual program. Have a look at the official mysql Dockerfile and entrypointto get an idea.

因此,一个典型的解决方案是拥有一个docker-entrypoint脚本。它检查它是否在启动其环境的新容器中运行,然后执行容器的实际程序。查看官方 mysql Dockerfile 和入口点以获得一个想法。

An example entrypoint script could look like this:

示例入口点脚本可能如下所示:

$ cat docker_entrypoint.sh                                                                                                                                          
if [ ! -f .initialized ]; then                                                                                                                                                                                    
    echo "Initializing container"                                                                                                                                                                                 
    # run initializing commands                                                                                                                                                                                   
    touch .initialized                                                                                                                                                                                            
fi                                                                                                                                                                                                                

exec "$@"

First, it checks whether there is a file called .initialized. If there is none, some commands are run to initialize the container environment. After which touch .initializedcreates .initializedas an empty file. Therefore, subsequent container starts won't execute the initialization command again. Secondly, it starts the actual service. Doing this with execwill replace the shell process with the service's process. Hence, docker will keep the container running until the service terminates. "$@"will contain the "container/image command". This is set with CMD Xin the Dockerfile and is overriden on the command, as I already pointed out above. By using exec "$@"you will be able to start different programs in the container for inspection, e.g. bash, and start the service by default, as specified in the Dockerfile's CMDstatement.

首先,它检查是否存在名为.initialized. 如果没有,则运行一些命令来初始化容器环境。之后touch .initialized创建.initialized为一个空文件。因此,后续容器启动不会再次执行初始化命令。其次,它启动了实际的服务。这样做exec会用服务的进程替换 shell 进程。因此,docker 将保持容器运行直到服务终止。"$@"将包含“容器/图像命令”。这是CMD X在 Dockerfile 中设置的,并在命令中被覆盖,正如我上面已经指出的那样。通过使用exec "$@"您将能够在容器中启动不同的程序进行检查,例如bash,并默认启动服务,如 Dockerfile 的CMD语句中指定的那样。

回答by helsonxiao

If you just want to initialize your db in the very first time, you can use this easy way.

如果您只想在第一次初始化您的数据库,您可以使用这种简单的方法。

    volumes:
      - [the scripts dir]:/docker-entrypoint-initdb.d

Initializing a fresh instance When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.

初始化一个新实例当一个容器第一次启动时,一个具有指定名称的新数据库将被创建并使用提供的配置变量进行初始化。此外,它将执行在 /docker-entrypoint-initdb.d 中找到的扩展名为 .sh、.sql 和 .sql.gz 的文件。文件将按字母顺序执行。您可以通过将 SQL 转储装载到该目录中并提供带有贡献数据的自定义图像来轻松填充您的 mysql 服务。默认情况下,SQL 文件将导入由 MYSQL_DATABASE 变量指定的数据库。

Doc is here: https://docs.docker.com/samples/library/mysql/

文档在这里:https: //docs.docker.com/samples/library/mysql/