Come si distribuisce un contenitore finestra mobile e un contenitore dati associato, inclusi i contenuti?


18

Inizierò ammettendo che sono abbastanza nuovo in Docker e potrei affrontare questo problema da una serie sbagliata di ipotesi ... fammi sapere se è così. Ho visto molte discussioni su come Docker sia utile per la distribuzione, ma nessun esempio di come è stato effettivamente fatto.

Ecco come pensavo che avrebbe funzionato:

  1. creare il contenitore dati per contenere alcuni dati persistenti sulla macchina A
  2. creare il contenitore dell'applicazione che utilizza i volumi dal contenitore dati
  3. fare un po 'di lavoro, potenzialmente cambiando i dati nel contenitore di dati
  4. arrestare il contenitore dell'applicazione
  5. commit e tag del contenitore dati
  6. spingere il contenitore di dati in un repository (privato)
  7. estrarre ed eseguire l'immagine dal passaggio 6 sulla macchina B
  8. riprendi da dove eri rimasto sulla macchina B

Il passaggio chiave qui è il passaggio 5, che pensavo avrebbe salvato lo stato corrente (compresi i contenuti del file system). È quindi possibile trasferire tale stato in un repository ed estrarlo da qualche altra parte, dandoti un nuovo contenitore che è essenzialmente identico all'originale.

Ma non sembra funzionare in questo modo. Quello che trovo è che il passaggio 5 non fa ciò che penso che faccia o il passaggio 7 (estrarre ed eseguire l'immagine) "ripristina" il contenitore al suo stato iniziale.

Ho messo insieme un insieme di tre immagini e contenitori Docker per testarlo: un contenitore di dati, uno scrittore che scrive una stringa casuale in un file nel contenitore di dati ogni 30 secondi e un lettore che semplicemente echoindica il valore nei dati file contenitore ed esce.

Contenitore dati

Creato con

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder

scrittore

Creato con

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done

Questo script scrive una stringa casuale e la data / ora /datafolder/data.txtnel contenitore dati.

Lettore

Creato con

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

Quando creo ed eseguo questi contenitori, funzionano perfettamente e funzionano come mi aspetto:

Stop & Start sulla macchina di sviluppo:

  1. creare il contenitore di dati
  2. gestisci lo scrittore
  3. avvia subito il lettore, vedi "nessun dato qui!" Messaggio
  4. aspetta un attimo
  5. eseguire il lettore, vedere la stringa casuale
  6. fermare lo scrittore
  7. riavvia lo scrittore
  8. eseguire il lettore, vedere la stessa stringa casuale

Ma impegnarsi e spingere non fa ciò che mi aspetto:

  1. creare il contenitore di dati
  2. gestisci lo scrittore
  3. avvia subito il lettore, vedi "nessun dato qui!" Messaggio
  4. aspetta un attimo
  5. eseguire il lettore, vedere la stringa casuale
  6. fermare lo scrittore
  7. commit e tag con il contenitore dati docker commit datatest_data myrepository:5000/datatest-data:latest
  8. spingere nel repository
  9. eliminare tutti i contenitori e ricrearli

A questo punto, mi aspetterei di eseguire il lettore e vedere la stessa stringa casuale, poiché il contenitore di dati è stato eseguito il commit, trasferito nel repository e quindi ricreato dalla stessa immagine nel repository. Tuttavia, quello che vedo effettivamente è il "nessun dato qui!" Messaggio.

Qualcuno può spiegare dove sto sbagliando qui? Oppure, in alternativa, mi indichi un esempio di come viene eseguita la distribuzione con Docker?

Risposte:


22

Hai sbagliato a supporre come funzionano i volumi nella finestra mobile. Proverò a spiegare in che modo i volumi si collegano ai contenitori della finestra mobile e alle immagini della finestra mobile e si spera che le differenze tra i volumi di dati e i contenitori di volumi di dati diventino chiare.

Per prima cosa ricordiamo alcune definizioni

Immagini docker

Le immagini Docker sono essenzialmente un filesystem union + metadati. È possibile controllare il contenuto del file system dell'unione delle immagini della finestra mobile con il docker exportcomando e controllare i metadati dell'immagine della finestra mobile con il docker inspectcomando.

Volumi di dati

dalla guida per l'utente Docker :

Un volume di dati è una directory appositamente designata all'interno di uno o più contenitori che bypassa il file system Union per fornire diverse utili funzioni per dati persistenti o condivisi.

È importante notare qui che un determinato volume (come la directory o il file che contiene dati) è riutilizzabile solo se esiste almeno un contenitore docker che lo utilizza. Le immagini Docker non hanno volumi, hanno solo metadati che alla fine indicano dove i volumi sarebbero montati sul filesystem union. I volumi di dati non fanno parte del filesystem union dei contenitori docker, quindi dove sono? in /var/lib/docker/volumessull'host docker (mentre i contenitori sono archiviati in /var/lib/docker/containers).

Contenitori del volume di dati

Quel tipo speciale di contenitore non ha nulla di speciale. Sono appena fermati i contenitori che utilizzano un volume di dati con l'unico ed unico obiettivo di avere almeno un contenitore che utilizza quel volume di dati. Ricorda, non appena viene eliminato l'ultimo contenitore (in esecuzione o arrestato) che utilizza un determinato volume di dati, quel volume diventerà irraggiungibile tramite l' opzione di esecuzione della finestra mobile--volumes-from .

Lavorare con i contenitori del volume di dati

Come creare un contenitore del volume di dati

L'immagine utilizzata per creare un contenitore del volume di dati non ha importanza in quanto un contenitore di questo tipo può rimanere fermo e riempire ancora il suo scopo. Quindi per creare un contenitore di dati denominato datatest_dataper un volume /datafolderè necessario solo eseguire:

docker run --name datatest_data --volume /datafolder busybox true

Ecco baseil nome dell'immagine (convenientemente piccolo) ed trueè un comando che forniamo solo per evitare di vedere il demone docker lamentarsi di un comando mancante. Ad ogni modo, dopo aver arrestato un container denominato datatest_datacon il solo scopo di consentire all'utente di raggiungere quel volume con l' --volumes-fromopzione del docker runcomando.

Come leggere da un contenitore del volume di dati

Conosco due modi per leggere un volume di dati: il primo è attraverso un contenitore. Se non è possibile disporre di una shell in un contenitore esistente per accedere a quel volume di dati, è possibile eseguire un nuovo contenitore con l' --volumes-fromopzione al solo scopo di leggere tali dati.

Per esempio:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

L'altro modo è copiare il volume dalla /var/lib/docker/volumescartella. Puoi scoprire il nome del volume in quella cartella ispezionando i metadati di uno dei container usando il volume. Vedi questa risposta per i dettagli.

Lavorare con i volumi (da Docker 1.9.0)

Come creare un volume (da Docker 1.9.0)

Docker 1.9.0 ha introdotto un nuovo comando docker volumeche consente di creare volumi:

docker volume create --name hello

Come leggere da un volume (da Docker 1.9.0)

Supponiamo che tu abbia creato un volume chiamato hellocon docker volume create --name hello, puoi montarlo in un contenitore con l' -vopzione:

docker run -v hello:/data busybox ls /data

Informazioni su commit e push dei container

Ora dovrebbe essere chiaro che, poiché i volumi di dati non fanno parte di un container (il filesystem union), il commit di un container per produrre una nuova immagine docker non conserverà alcun dato che si troverebbe in un volume di dati.

Esecuzione di backup dei volumi di dati

La guida per l'utente della finestra mobile contiene un bell'articolo sulla creazione di backup dei volumi di dati .


Volumi di buona risposta dell'articolo: http://container42.com/2014/11/03/docker-indepth-volumes/


Sembra che "l'immagine utilizzata per creare un contenitore del volume di dati non abbia importanza" non è del tutto corretta. Prova con un'immagine "scratch" che ti darà "exec:" true ": file eseguibile non trovato"
tcurdt

Nonostante questo errore, il tuo contenitore verrà creato per adempiere al suo ruolo di detentore del volume
Thomasleveil,

1
Hm - forse vale la pena aprire un problema per quello.
martedì

no, quel comportamento è previsto poiché l'immagine scratch è un'immagine vuota che non può avere comunque il /bin/truebinario (o nessun altro)
Thomasleveil,

1
Solo una cosa. Hai detto che "non appena viene eliminato l'ultimo contenitore (in esecuzione o arrestato) che utilizza un determinato volume di dati, la finestra mobile distruggerà quel volume di dati da / var / lib / docker / volumi.", Ma ciò non è effettivamente vero: basta vedere: docs.docker.com/userguide/dockervolumes (I volumi di dati persistono anche se il contenitore stesso viene eliminato. È necessario specificare il docker rm -vcomando sull'ultimo contenitore per eliminare anche un volume)
juanra

1

È inoltre possibile utilizzare un contenitore di dati docker per distribuire il codice

Non so se sia una buona pratica, ma lo faccio così:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

Ora puoi spingere la tua immagine e usare i volumi da, ecc ...


Questo è quello che sto cercando, ma la risposta accettata menziona esplicitamente che non è possibile farlo. Lo proverò adesso.
andho,

1
A un secondo sguardo, la risposta accettata afferma che i volumi (o i dati al suo interno) non verranno sottoposti a commit, ma è possibile aggiungere i dati nel contenitore usando COPYo ADDe creare il volume usando VOLUMEnel Dockerfile.
andho,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.