2016-05-26 13 views
13

È la prima volta che lavoro con Docker e non sono sicuro se sto facendo bene le cose.Docker, come eseguire il file .sql in un'immagine?

Ho un applicazioni Rails che dipende da un database diMysql, quindi ho configurato il file docker-compose.yml in questo modo:

db: 
    image: library/mysql:5.6 
    environment: 
    MYSQL_ALLOW_EMPTY_PASSWORD: "yes" 
    expose: 
    - "3306" 
    ports: 
    - "3306:3306" 

rails-app: 
    build: . 
    dockerfile: Dockerfile 
    environment: 
    RAILS_ENV: development 
    links: 
    - db 
    volumes: 
    - ".:/home/app" 
    volumes_from: 
    - bundle 

    ... omitted lines ... 

Poi, se corro il seguente:

$ docker-compose run db mysql --host=$DOCKER_LOCALHOST --port=3306 --protocol=tcp -u root < shared/create_common_tables.sql 

ottengo questo errore:

ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.99.100' (111) 

questo sou nds normale, perché ho il sospetto che devo build prima di un contenitore che si collega a db.

Lo so perché se corro questo in questo ordine:

$ docker-compose build rails-app 
$ docker-compose run -e RAILS_ENV=development rails-app bundle 
$ docker-compose run -e RAILS_ENV=development rails-app bundle exec rake db:create 
$ docker-compose run db mysql --host=$DOCKER_LOCALHOST --port=3306 --protocol=tcp -u root < shared/create_common_tables.sql 

Funziona benissimo.

Ma, come posso eseguire questo SQL prima di creare qualsiasi contenitore?

risposta

7

È possibile caricare il file sql durante la fase build dell'immagine. Per fare questo si crea un Dockerfile per il db servizio che avrà un aspetto simile a questo:

FROM mysql:5.6 
COPY setup.sh /mysql/setup.sh 
COPY setup.sql /mysql/setup.sql 
RUN /mysql/setup.sh 

dove setup.sh sembra qualcosa di simile:

#!/bin/bash 
set -e 
service mysql start 
mysql < /mysql/setup.sql 
service mysql stop 

E nel tuo docker-compose.yml che ci si cambia image-build: ./db o il percorso in cui metti i tuoi file.

Ora questo funziona se si dispone di tutti i file sql in un file .sql non elaborato, ma questo non si verifica se si utilizzano i binari o un framework simile in cui lo sql è effettivamente memorizzato nel codice. Questo ti lascia con due opzioni.

  1. Invece di utilizzare FROM mysql:5.6 è possibile utilizzare FROM your_app_image_that_has_the_code_in_it e apt-get install mysql .... Questo ti lascia con un'immagine più grande che contiene sia mysql che la tua app, permettendoti di eseguire i comandi ruby ​​sopra. Sostituire lo mysql < /mysql/setup/sql con le linee rails-app bundle exec rake db:create. Faresti anche necessario fornire una configurazione app che colpisce un database su localhost:3306 invece di db:3306

  2. mia opzione preferita è quella di creare uno script che esporta il codice SQL in un file .sql, che è possibile utilizzare per costruire la vostra base di dati contenitore. Questo è un po 'più di lavoro, ma è molto più bello. Significa che invece di eseguire rails-app bundle exec rake db:create devi solo eseguire lo script per caricare un db.

Tale uno script sarebbe simile a questa:

#!/bin/bash 
set -e 
docker-compose build rails-app 
docker run -d --name mysql_empty mysql:5.6 
docker run --link mysql_empty:db -v $PWD:/output project_rails-app export.sh 

dove export.sh sembra qualcosa di simile:

#!/bin/bash 
set -e 
RAILS_ENV=development 
rails-app bundle exec rake db:create 
mysqldump > /output/setup.sql 

Si può anche sostituire lo script docker run con un secondo file composizione se volevi.

+3

L'immagine docker MySQL ha già un meccanismo per inizializzare un nuovo contenitore con i dati. Carica tutti i file .sh e .sql da /docker-entrypoint-initdb.d, è sufficiente copiare o montare dall'host alla directory. Vedere https://hub.docker.com/_/mysql/ in "Inizializzazione di una nuova istanza" – diwo

+3

Sì, ma quel meccanismo non si adatta al requisito nella domanda "come posso fare per eseguire questo sql prima di creare qualsiasi contenitore". Personalmente non penso che i dispositivi di carico come parte del punto di accesso siano una buona soluzione. Richiede di ripetere il processo ogni volta che si crea il contenitore, il che rallenta notevolmente il tempo di avvio. – dnephin

Problemi correlati