2015-09-09 5 views
15

Vorrei creare un'immagine di Docker MySQL con dati già compilati.Come creare un'immagine MySQL Docker popolata sul tempo di costruzione

voglio creare 3 strati in questo modo:

 |---------------------|---------------------| 
Layer 3 | Customer 1 Database | Customer 2 Database | 
     |---------------------|---------------------| 
Layer 2 | Database image with tables but no data | 
     |-------------------------------------------| 
Layer 1 |    mysql:5.6.26    | 
     |-------------------------------------------| 

La mia domanda è ora come creare una corretta Dockerfile per layer 2 e 3? Dove il mio file empty_with_tables.sql è caricato nel layer 2 e customer1.sql e customer2.sql sono caricati in due immagini nel layer 3. Ho letto qualcosa sul mettere i file SQL in "/docker-entrypoint-initdb.d". Ma questo comporterebbe il fatto che i dati siano quando l'immagine viene avviata per la prima volta. Questo non è quello che voglio. Voglio che i dati siano pronti nell'immagine (ad esempio per essere rapidamente disponibili nei test).

Potrei avviare l'immagine mysql, caricare i dati da linea di comando e fare un 'commit' ma questo non è riproducibile, richiedendo di farlo di nuovo quando i dati nei file SQL vengono modificati.

Come si può fare?

Con i migliori saluti,

  • Morten Green Hermansen

risposta

3

Quindi la mia soluzione a questo problema era solo NON di sovrapporre tutto ma creare un'immagine di base e utilizzare --volumes-from per iniettare i file del database da un contenitore di soli dati.

+4

Puoi fornire maggiori informazioni, per favore? Mi piacerebbe farlo anche io. – Telokis

+1

@Morten Green per favore prenditi del tempo e condividi il tuo lavoro, siamo qui per aiutarci a vicenda. – Dung

4

Questo non può essere fatto in modo pulito il modo esatto si vuole che, almeno quando basando immagine ufficiale mysql avanti, perché è necessario comunicare con il server per importare i dati e il server non viene eseguito e inizializzato (da mysql's docker-entrypoint.sh) finché non viene eseguito il contenitore, che è solo quando l'immagine è già stata creata.

Il modo non-così-pulito è quello di eseguire il processo nel contenitore, utilizzando lo script /entrypoint.sh immagine mysql da, ma si deve prendere cura di tutte le impostazioni necessarie dal entrypoint (come $MYSQL_ROOT_PASSWORD), così come un ambiente pulito modo per fermare il demone subito dopo aver importato i dati. Qualcosa di simile:

FROM mysql:5.6 

ADD data.sql /docker-entrypoint-initdb.d/00-import-data.sql 
ENV MYSQL_ROOT_PASSWORD somepassword 
ENV MYSQL_DATABASE db1 
RUN /entrypoint.sh mysqld & sleep 30 && killall mysqld 

è un modo hacker che si traduce in DB pre-inizializzato, ma ... non funziona. Il motivo è che /var/lib/mysql viene dichiarato come volume nel Dockerfile di mysql e qualsiasi modifica a questa directory durante il processo di generazione viene persa dopo aver completato il passo di generazione. Questo può essere osservato nella seguente Dockerfile:

FROM mysql:5.6 

RUN touch /var/lib/mysql/some-file && ls /var/lib/mysql 
RUN touch /var/lib/mysql/some-file2 && ls /var/lib/mysql 

Quindi suggerisco di andare con docker commit come hai descritto. Il risultato finale è uguale a quello che si desidera ottenere, con l'eccezione del Livello 2 forse.

UPDATE: Come OP commentato di seguito, il commit non contiene volumi. Quindi, l'unico modo sembra essere quello di modificare MySQL Dockerfile e rimuovere VOLUME per mantenere i dati all'interno del contenitore, o per gestire i volumi separatamente dai contenitori.

+1

Ciao! Mi dispiace per la risposta in ritardo! Non c'è un problema con il metodo di commit? nel Dockerfile ufficiale viene definito un volume ('VOLUME/var/lib/mysql') e questo è proprio dove si trovano i database. Pertanto un commit non includerà quei file in una nuova immagine (ho fatto un controllo con 'docker diff '). E non posso montare un volume? –

+0

Hai ragione; questo è un problema generale con volumi opachi a qualsiasi commit (quindi non funziona durante la compilazione). Vedi https://github.com/docker/docker/issues/6999. Generalmente le persone clonano il repository originale e spostano VOLUME dopo le loro modifiche personalizzate, oppure rimuovono tutto insieme - vedi https://github.com/stuartpb/rethinkdb-dockerfiles/issues/14 – pwes

15

Ho avuto lo stesso problema questa settimana.Ho trovato una soluzione di lavoro senza la necessità di --volumes-from

Il problema che è già affermato è che /var/lib/mysql è un volume, e dal momento che Docker non ha intenzione di sostenere UNVOLUME nella sua Dockerfile in un prossimo futuro, non è possibile utilizzare questa posizione per la memoria del database se si desidera iniziare con un database vuoto per impostazione predefinita. (https://github.com/docker/docker/issues/18287). Ecco perché sovrascrivo lo etc/mysqld.my.cnf, dando a mysql un nuovo datadir.

Insieme pwes' la sua risposta, è possibile creare un Dockerile come questo:

FROM mysql:5.6 

ENV MYSQL_DATABASE db 
ENV MYSQL_ROOT_PASSWORD pass 
COPY db.sql /docker-entrypoint-initdb.d/db.sql 
COPY my.cnf /etc/mysql/my.cnf 
RUN /entrypoint.sh mysqld & sleep 30 && killall mysqld 
RUN rm /docker-entrypoint-initdb.d/db.sql 

L'unico cambiamento è in my.cnf è la posizione del datadir:

.... 
[mysqld] 
skip-host-cache 
skip-name-resolve 
user  = mysql 
pid-file = /var/run/mysqld/mysqld.pid 
socket  = /var/run/mysqld/mysqld.sock 
port  = 3306 
basedir  = /usr 
datadir  = /var/lib/mysql2 <-- can be anything except /var/lib/mysql 
tmpdir  = /tmp 
lc-messages-dir = /usr/share/mysql 
explicit_defaults_for_timestamp 
.... 
+0

Bel lavoro con il dettaglio MW – Drew

4

Sulla MegaWubs di risposta, ho trovato questo Dockerfile sufficiente.

FROM mysql:5.6 
RUN sed -i 's|/var/lib/mysql|/var/lib/mysql2|g' /etc/mysql/my.cnf 
+1

Usando mysql: 5.7, ho usato: '' 'RUN sed -i '|/var/lib/mysql |/var/lib/mysql2 | g'/etc/mysql/mysql. conf.d/mysqld.cnf''' –

Problemi correlati