2017-02-08 16 views
9

Staram się, aby mój proces deweloperski był łatwiejszy/łatwiejszy w obsłudze za pomocą funkcji dokowania (-kompilacja). Nie chcę używać żadnych woluminów (jeśli to możliwe). Dlaczego import.sh nie zostanie wykonany po uruchomieniu 'docker-compose up -d'?Jak wykonać skrypty po utworzeniu dokera?

mam następujące pliki:

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

w doker-compose.yml znajduje się:

version: '2' 

services: 
    database: 
    image: mysql 
    build: 
     context: ./mysql/ 
     dockerfile: Dockerfile 
    container_name: mysqltest 
    ports: 
     - "3306:3306" 
    environment: 
     MYSQL_ROOT_PASSWORD: 123456 

w /mysql/Dockerfile znajduje się:

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

w /mysql/db.sql znajduje się:

CREATE DATABASE test1; 
CREATE DATABASE test2; 
CREATE DATABASE test3; 
+0

Plik Dockerfile zostanie uruchomiony, gdy obraz będzie _built_. Kompilacja Docker skompiluje obraz przed uruchomieniem. Zatem Twój skrypt powinien działać _przed uruchomieniem 'docker-compose up -d', a nie _ po tym. – mkasberg

+2

Wygląda na to, że chcesz tylko zrzutu bazy danych uruchomić _ po uruchomieniu demona mysql. W takim przypadku użyj '/ docker-entrypoint-initdb.d', Udokumentowano na [MySQL Dockerhub Page] (https://hub.docker.com/_/mysql/), a także wyjaśniono tutaj: http: // stackoverflow .pl/questions/36781984/load-postgres-dump-after-docker-compose-up/36782751 # 36782751 (działa tak samo dla PostgreSQL i MySQL). – mkasberg

+1

Tak, właśnie to chciałem osiągnąć i zadziałało to dla mnie, dziękuję. Ale co jeśli chcę uruchomić inne skrypty po procesie kompilacji/kiedy wszystkie kontenery są gotowe? – p0rter

Odpowiedz

8

Można użyć ENTRYPOINT lub CMD w Dockerfile do wykonania polecenia, gdy zaczyna kontenerów. Różnica między nimi polega na tym, że ENTRYPOINT jest wykonywany za każdym razem, gdy kontener jest uruchamiany, podczas gdy CMD może zostać zastąpiony przez opcję wiersza poleceń. Zakładając, że polecenie, które chcesz wykonać jest X

docker run my-image Y 

wykona X jeśli ENTRYPOINT X był w Dockerfile i Y jeśli CMD X był w Dockerfile.

Istnieją jednak dwa zastrzeżenia:

  1. Polecenie zostanie wykonane za każdym razem, gdy pojemnik jest uruchamiany.
  2. Po zakończeniu polecenia kontener zostaje zamknięty.

Dlatego typowym rozwiązaniem jest posiadanie skryptu docker-entrypoint. Sprawdza, czy działa on w nowym kontenerze inicjującym jego środowisko, a następnie wykonuje rzeczywisty program kontenera. Zapoznaj się z official mysql Dockerfile and entrypoint, aby uzyskać pomysł.

Przykładowy skrypt punkt_wejścia mógłby wyglądać następująco:

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

exec "[email protected]" 

Najpierw sprawdza czy istnieje plik o nazwie .initialized. Jeśli nie ma, niektóre polecenia są uruchamiane w celu zainicjowania środowiska kontenera. Po czym touch .initialized tworzy .initialized jako pusty plik. Dlatego kolejne uruchomienia kontenera nie będą ponownie wykonywać komendy inicjowania. Po drugie, rozpoczyna rzeczywistą usługę. Wykonanie tej czynności za pomocą exec spowoduje zastąpienie procesu powłoki procesem usługi. Dlatego dokowanie będzie utrzymywało kontener do momentu zakończenia usługi. "[email protected]" będzie zawierał "komendę kontener/obraz". Jest to ustawione w CMD X w pliku Dockerfilm i jest nadpisywane zgodnie z poleceniem, jak już wskazałem powyżej. Dzięki użyciu exec "[email protected]" będziesz mógł uruchamiać różne programy w kontenerze do inspekcji, np. bash i usługa jest domyślnie uruchamiana zgodnie z instrukcjami podanymi w instrukcji Dockerfile: CMD.

Powiązane problemy