2017-02-08 10 views
9

Я пытаюсь сделать мой процесс dev более легким/поддерживаемым с помощью docker (-compose). Я не хочу использовать тома (если это возможно). Почему import.sh не выполняется после запуска «docker-compose up -d»?Как выполнить скрипты после компоновки докеров?

У меня есть следующие файлы:

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

в докер-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

Файл Dockerfile запускается, когда изображение _built_. Docker Compose создаст для вас образ, прежде чем запускать его. Таким образом, ваш скрипт должен быть запущен _before_, вы запускаете 'docker-compose up -d', а не _after_. – mkasberg

+2

Похоже, вы просто хотите, чтобы дамп базы данных запускался _after_ запускает демон mysql. В этом случае используйте '/ docker-entrypoint-initdb.d', задокументированный на странице [MySQL Dockerhub Page] (https://hub.docker.com/_/mysql/), а также здесь: http: // stackoverflow .com/questions/36781984/load-postgres-dump-after-docker-compose-up/36782751 # 36782751 (функции одинаковы для Postgres и MySQL). – mkasberg

+1

Да, это то, чего я хотел достичь, и это сработало для меня, спасибо. Но что делать, если я хочу запускать другие скрипты после процесса сборки/когда все контейнеры готовы? – p0rter

ответ

8

Вы можете использовать ENTRYPOINT или CMD в вашем Dockerfile, чтобы выполнить команду, когда контейнер начинается. Разница между ними заключается в том, что ENTRYPOINT выполняется при каждом запуске контейнера, а CMD может быть заменен параметром командной строки. Предполагая команду, которую вы хотите выполнить это X

docker run my-image Y 

выполнит X если ENTRYPOINT X был в Dockerfile и Y если CMD X был в Dockerfile.

Однако есть два предостережения:

  1. Команда будет выполняться каждый раз при запуске контейнера.
  2. После завершения команды контейнер закрыт.

Таким образом, типичным решением является наличие сценария docker-entrypoint. Он проверяет, запускается ли он в новом контейнере, запускающем его среду, а затем выполняет фактическую программу контейнера. Посмотрите на official mysql Dockerfile and entrypoint, чтобы узнать об этом.

Пример EntryPoint сценарий может выглядеть следующим образом:

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

exec "[email protected]" 

Во-первых, он проверяет, существует ли файл с именем .initialized. Если их нет, некоторые команды запускаются для инициализации среды контейнера. После чего touch .initialized создает .initialized в виде пустого файла. Поэтому последующие запуска контейнера не будут снова выполнять команду инициализации. Во-вторых, он начинает фактическое обслуживание. Выполнение этого с помощью exec заменит процесс оболочки процессом обслуживания. Следовательно, докер будет поддерживать контейнер до тех пор, пока служба не завершится. "[email protected]" будет содержать команду «контейнер/изображение». Это задано с CMD X в файле Dockerfile и переопределяется командой, как я уже указывал выше. Используя exec "[email protected]", вы сможете запускать различные программы в контейнере для проверки, например. bash и запустить службу по умолчанию, как указано в инструкции CMD Dockerfile.