如何在docker-compose之后执行脚本?

时间:2017-02-08 15:37:15

标签: mysql docker docker-compose

我试图使用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;

2 个答案:

答案 0 :(得分:19)

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

docker run my-image Y
如果X在Dockerfile中,

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

但是,有两点需要注意:

  1. 每次启动容器时都会执行该命令。
  2. 命令终止后,容器将关闭。
  3. 因此,典型的解决方案是使用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变量指定的数据库中。

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