Come gestire l'archiviazione persistente (ad es. Database) in Docker


993

In che modo le persone gestiscono l'archiviazione persistente dei contenitori Docker?

Attualmente sto usando questo approccio: costruire l'immagine, ad esempio per PostgreSQL, e quindi avviare il contenitore con

docker run --volumes-from c0dbc34fd631 -d app_name/postgres

IMHO, che ha lo svantaggio, che non devo mai (per caso) cancellare il contenitore "c0dbc34fd631".

Un'altra idea sarebbe quella di montare i volumi host "-v" nel contenitore, tuttavia l' id utente all'interno del contenitore non corrisponde necessariamente all'id utente dell'host e quindi le autorizzazioni potrebbero essere incasinate.

Nota: invece di --volumes-from 'cryptic_id'te puoi anche usare --volumes-from my-data-containerdove si my-data-containertrova un nome assegnato a un contenitore di soli dati, ad es. docker run --name my-data-container ...(Vedi la risposta accettata)


Scusate, ho sbagliato a dire che intendevo dire: tutte le mie istanze future di quell'immagine dipendono da quel contenitore. Se cancello quel contenitore per sbaglio, sono nei guai.
juwalter,

@AntonStrogonoff - sì, errore di fraseggio - Volevo dire: devo assicurarmi di non eliminare mai quel contenitore (possibilmente) vecchio, perché poi
sparirebbe

dovrebbe essere --name. hai-name
Shammel Lee il

Risposte:


986

Docker 1.9.0 e versioni successive

Usa API volume

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command

Ciò significa che il modello contenitore solo dati deve essere abbandonato a favore dei nuovi volumi.

In realtà l'API del volume è solo un modo migliore per ottenere quello che era il modello del contenitore di dati.

Se si crea un contenitore con una -v volume_name:/container/fs/pathfinestra mobile, verrà automaticamente creato un volume con nome che può:

  1. Essere elencati attraverso il docker volume ls
  2. Essere identificato attraverso il docker volume inspect volume_name
  3. Backup come una directory normale
  4. Effettuato il backup come prima tramite una --volumes-fromconnessione

La nuova API del volume aggiunge un utile comando che consente di identificare i volumi sospesi:

docker volume ls -f dangling=true

E poi rimuovilo con il suo nome:

docker volume rm <volume name>

Come sottolinea @mpugach nei commenti, puoi sbarazzarti di tutti i volumi sospesi con una bella copertina:

docker volume rm $(docker volume ls -f dangling=true -q)
# Or using 1.13.x
docker volume prune

Docker 1.8.xo inferiore

L'approccio che sembra funzionare meglio per la produzione consiste nell'utilizzare un contenitore di soli dati .

Il contenitore di soli dati viene eseguito su un'immagine barebone e in realtà non fa altro che esporre un volume di dati.

Quindi è possibile eseguire qualsiasi altro contenitore per avere accesso ai volumi del contenitore dati:

docker run --volumes-from data-container some-other-container command-to-execute
  • Qui puoi avere una buona immagine di come organizzare i diversi contenitori.
  • Qui c'è una buona visione di come funzionano i volumi.

In questo post del blog c'è una buona descrizione del cosiddetto contenitore come modello di volume che chiarisce il punto principale di avere solo contenitori di dati .

La documentazione Docker ha ora la descrizione DEFINITIVA del contenitore come modello volume / i .

Di seguito è la procedura di backup / ripristino per Docker 1.8.xe inferiore.

BACKUP:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
  • --rm: rimuove il contenitore quando esce
  • --volumes-from DATA: allega ai volumi condivisi dal contenitore DATA
  • -v $ (pwd): / backup: bind monta la directory corrente nel contenitore; per scrivere il file tar in
  • busybox: una piccola immagine più semplice - buona per una manutenzione rapida
  • tar cvf /backup/backup.tar / data: crea un file tar non compresso di tutti i file nella directory / data

RISTABILIRE:

# Create a new data container
$ sudo docker run -v /data -name DATA2 busybox true
# untar the backup files into the new container᾿s data volume
$ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
data/
data/sven.txt
# Compare to the original container
$ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data
sven.txt

Ecco un bell'articolo dell'eccellente Brian Goff che spiega perché è bene usare la stessa immagine per un contenitore e un contenitore di dati.


8
È uno strumento diverso per un'esigenza diversa. --volumes-fromti consente di condividere lo spazio su disco --linkti consente di condividere i servizi.
Tommasop,

3
C'è un altro progetto nelle opere specificamente pensato per questo tipo di cose, forse aggiungerlo a questa risposta come riferimento da guardare? github.com/ClusterHQ/flocker
Andre

9
I contenitori di dati non hanno alcun significato e sono davvero una cattiva idea! Contenitore significa qualcosa solo quando un processo è in esecuzione in questo, altrimenti è solo un pezzo di file system host. Puoi semplicemente montare un volume con -v che è l'unica e la migliore opzione. Hai il controllo sul filesystem e sul disco fisico che usi.
Boynux,

11
Sì, a partire da Docker 1.9, la creazione di Volumi con nome con l'API Volumi ( docker volume create --name mydata) è preferita rispetto a un contenitore di volumi di dati. Gli stessi utenti Docker suggeriscono che i contenitori di volumi di dati " non sono più considerati uno schema consigliato ", "i volumi con nome dovrebbero essere in grado di sostituire i volumi di soli dati nella maggior parte dei casi (se non tutti) " e " nessun motivo che posso vedere per usare contenitori solo dati . "
Quinn Comendant,

8
@coding, sono triste, sei triste, in parte perché stai giudicando le risposte con un ritardo di 3 anni e in parte perché la risposta è sostanzialmente giusta in tutta la sua storia. Se hai qualche consiglio sentiti libero di commentare in modo che io possa integrare la risposta e aiutare le persone a non essere tristi
tommasop

75

Nella versione Docker v1.0 , l'associazione di un file o di una directory sul computer host può essere eseguita dal comando dato:

$ docker run -v /host:/container ...

Il volume sopra potrebbe essere usato come memoria persistente sull'host che esegue Docker.


3
Questa dovrebbe essere la risposta raccomandata in quanto è molto meno complessa dell'approccio volume-container che al momento ha più voti
insitusec

2
Vorrei che ci fosse una bandiera per specificare un host-uid: container-uid e host-gid: container-gid quando si usa questo comando volume mount.
rampion

35

A partire da Docker Compose 1.6, ora è stato migliorato il supporto per i volumi di dati in Docker Compose. Il seguente file di composizione creerà un'immagine di dati che persisterà tra i riavvii (o persino la rimozione) dei contenitori padre:

Ecco l'annuncio del blog: Compose 1.6: Nuovo file Compose per la definizione di reti e volumi

Ecco un esempio di file di composizione:

version: "2"

services:
  db:
    restart: on-failure:10
    image: postgres:9.4
    volumes:
      - "db-data:/var/lib/postgresql/data"
  web:
    restart: on-failure:10
    build: .
    command: gunicorn mypythonapp.wsgi:application -b :8000 --reload
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

volumes:
  db-data:

Per quanto posso capire: questo creerà un contenitore del volume di dati ( db_data) che persisterà tra i riavvii.

Se corri: docker volume lsdovresti vedere il tuo volume elencato:

local               mypthonapp_db-data
...

Puoi ottenere ulteriori dettagli sul volume di dati:

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]

Alcuni test:

# Start the containers
docker-compose up -d

# .. input some data into the database
docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py createsuperuser
...

# Stop and remove the containers:
docker-compose stop
docker-compose rm -f

# Start it back up again
docker-compose up -d

# Verify the data is still there
...
(it is)

# Stop and remove with the -v (volumes) tag:

docker-compose stop
docker=compose rm -f -v

# Up again ..
docker-compose up -d

# Check the data is still there:
...
(it is).

Appunti:

  • È inoltre possibile specificare vari driver nel volumesblocco. Ad esempio, è possibile specificare il driver Flocker per db_data:

    volumes:
      db-data:
        driver: flocker
    
  • Mentre migliorano l'integrazione tra Docker Swarm e Docker Compose (e forse iniziano a integrare Flocker nell'ecosistema Docker (ho sentito dire che Docker ha acquistato Flocker), penso che questo approccio dovrebbe diventare sempre più potente.

Disclaimer: questo approccio è promettente e lo sto usando con successo in un ambiente di sviluppo. Sarei preoccupato di usare questo in produzione ancora!


Flocker è stato chiuso e non c'è molta attività nel repository github
Krishna

17

Nel caso in cui non sia chiaro dall'aggiornamento 5 della risposta selezionata, a partire da Docker 1.9, è possibile creare volumi che possono esistere senza essere associati a un contenitore specifico, rendendo così obsoleto il modello "contenitore solo dati".

Vedi Contenitori solo dati obsoleti con la finestra mobile 1.9.0? # 17798 .

Penso che i manutentori di Docker abbiano capito che il modello di contenitore di soli dati era un po 'un odore di progettazione e ho deciso di rendere i volumi un'entità separata che può esistere senza un contenitore associato.


13

Mentre questa è ancora una parte di Docker che necessita di un po 'di lavoro , è necessario inserire il volume nel Dockerfile con l'istruzione VOLUME modo da non dover copiare i volumi da un altro contenitore.

Ciò renderà i vostri contenitori meno interdipendenti e non dovrete preoccuparvi della cancellazione di un contenitore che interessa un altro.


L'argomento rovescio della medaglia è che i contenitori "solo dati" finiscono per essere il riferimento dell'ultima risorsa al volume di dati (Docker distrugge i volumi di dati una volta che l'ultimo contenitore che fa riferimento a quel volume viene rimosso con docker rm)
WineSoaked

2
Questa guida ufficiale di Docker suggerisce altrimenti: docs.docker.com/userguide/dockervolumes/… "I volumi di dati sono progettati per conservare i dati, indipendentemente dal ciclo di vita del contenitore. Docker pertanto non eliminerà mai automaticamente i volumi quando si rimuove un contenitore, né lo farà Volumi "garbage collection" a cui non fa più riferimento un contenitore ".
Alex,

12

Quando si utilizza Docker Compose , è sufficiente collegare un volume con nome, ad esempio:

version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - db_data:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: root
volumes:
  db_data:

9

La risposta di @ tommasop è buona e spiega alcuni dei meccanismi di utilizzo dei contenitori di soli dati. Ma come qualcuno che inizialmente pensava che i contenitori di dati fossero sciocchi quando si poteva semplicemente associare un volume all'host (come suggerito da molte altre risposte), ma ora si rende conto che in realtà i contenitori di soli dati sono piuttosto puliti, posso suggerire il mio post sul blog su questo argomento: Perché i contenitori di dati Docker (Volumi!) sono buoni

Vedi anche: la mia risposta alla domanda " Qual è il modo (migliore) per gestire le autorizzazioni per i volumi condivisi Docker? " Per un esempio di come utilizzare i contenitori di dati per evitare problemi come le autorizzazioni e il mapping uid / gid con l'host.

Per affrontare una delle preoccupazioni iniziali del PO: che il contenitore di dati non deve essere cancellato. Anche se il contenitore di dati viene eliminato, i dati stessi non andranno persi fintanto che un contenitore ha un riferimento a quel volume, ovvero qualsiasi contenitore che ha montato il volume tramite --volumes-from. Quindi, a meno che tutti i relativi contenitori non vengano arrestati ed eliminati (si potrebbe considerare l'equivalente di un accidentale rm -fr /) i dati sono al sicuro. È sempre possibile ricreare il contenitore dati eseguendo --volumes-fromqualsiasi contenitore che abbia un riferimento a quel volume.

Come sempre, fai i backup!

AGGIORNAMENTO: Docker ora dispone di volumi che possono essere gestiti indipendentemente dai container, il che semplifica ulteriormente la gestione.


9

Esistono diversi livelli di gestione dei dati persistenti, a seconda delle esigenze:

  • Conservalo sul tuo host
    • Usa la bandiera -v host-path:container-path per conservare i dati della directory del contenitore in una directory host.
    • I backup / ripristini avvengono eseguendo un contenitore di backup / ripristino (come tutumcloud / dockup) montato nella stessa directory.
  • Creare un contenitore di dati e montarne i volumi sul contenitore dell'applicazione
    • Creare un contenitore che esporta un volume di dati, utilizzare --volumes-from per montare tali dati nel contenitore dell'applicazione.
    • Backup / ripristino uguale alla soluzione sopra.
  • Utilizzare un plug-in del volume Docker che supporti un servizio esterno / di terze parti
    • I plug-in del volume Docker consentono all'origine dati di provenire da qualsiasi luogo: NFS, AWS (S3, EFS ed EBS)
    • A seconda del plug-in / servizio, è possibile collegare contenitori singoli o multipli a un singolo volume.
    • A seconda del servizio, i backup / ripristini possono essere automatizzati per te.
    • Mentre questo può essere complicato da eseguire manualmente, alcune soluzioni di orchestrazione - come Rancher - lo hanno cotto e semplice da usare.
    • Convoy è la soluzione più semplice per farlo manualmente.

8

Se vuoi spostare i tuoi volumi, dovresti anche guardare Flocker .

Dal README:

Flocker è un gestore di volumi di dati e uno strumento di gestione dei cluster Docker multihost. Con esso puoi controllare i tuoi dati usando gli stessi strumenti che usi per le tue applicazioni senza stato sfruttando la potenza di ZFS su Linux.

Ciò significa che è possibile eseguire database, code e archivi di valori-chiave in Docker e spostarli facilmente come il resto dell'applicazione.


1
Grazie Johann. Lavoro in ClusterHQ e volevo solo notare che ci siamo spostati oltre lo storage basato su ZFS. Ora puoi utilizzare Flocker con spazio di archiviazione come Amazon EBS o Google Persistent Disk. Ecco un elenco completo delle opzioni di archiviazione: docs.clusterhq.com/en/latest/supported/…
ferrantim,

1
Flocker è cessato e non dovrebbe essere usato portworx.com/…
jesugmz

5

Dipende dal tuo scenario (questo non è davvero adatto per un ambiente di produzione), ma qui è un modo:

Creazione di un contenitore Docker MySQL

Questa idea è di utilizzare una directory sull'host per la persistenza dei dati.


6
Grazie Ben, tuttavia - uno dei problemi che posso vedere con questo approccio: la risorsa del file system (directory, file) sarebbe di proprietà di un uid all'interno del contenitore docker / lxc (guest) - uno che potrebbe eventualmente scontrarsi con un uid sull'host ...
juwalter,

1
penso che tu sia abbastanza sicuro in quanto è gestito da root, ma sono d'accordo che sia un hack - adatto al meglio a test di integrazione effimeri / dev locali. Questa è sicuramente un'area che mi piacerebbe vedere emergere più modelli / pensieri. Dovresti dare un'occhiata / pubblicare questa domanda al gruppo docker-dev google
ben schwartz

Ben, grazie per questa soluzione! Non lo definirei un trucco però, sembra molto più affidabile del contenitore come volume . Vedete degli svantaggi nel caso in cui i dati vengano utilizzati esclusivamente dal contenitore? (L'UID non ha importanza in questo caso)
johndodo,



0

La mia soluzione è quella di utilizzare il nuovo docker cp, che ora è in grado di copiare i dati dai contenitori, non importa se è in esecuzione o meno e condividere un volume host nello stesso identico percorso in cui l'applicazione di database sta creando i suoi file di database all'interno del contenitore . Questa doppia soluzione funziona senza un contenitore di soli dati, direttamente dal contenitore del database originale.

Quindi il mio script di systemd init sta eseguendo il backup del database in un archivio sull'host. Ho inserito un timestamp nel nome del file per non riscrivere mai un file.

Lo sta facendo su ExecStartPre:

ExecStartPre=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStartPre=-/bin/bash -c '/usr/bin/tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStartPre.tar.gz /home/core/sql/mysql --remove-files'

E sta facendo la stessa cosa anche su ExecStopPost:

ExecStopPost=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStopPost=-/bin/bash -c 'tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStopPost.tar.gz /home/core/sql/mysql --remove-files'

Inoltre ho esposto una cartella dall'host come volume nello stesso identico percorso in cui è archiviato il database:

mariadb:
  build: ./mariadb
  volumes:
    - $HOME/server/mysql/:/var/lib/mysql/:rw

Funziona benissimo sulla mia VM (sto costruendo uno stack LEMP per me stesso): https://github.com/DJviolin/LEMP

Ma non so se si tratta di una soluzione "a prova di proiettile" quando la tua vita in realtà dipende da essa (ad esempio, negozio online con transazioni in eventuali millisecondi)?

A 20 minuti e 20 secondi da questo video keynote ufficiale di Docker, il presentatore fa la stessa cosa con il database:

Introduzione a Docker

"Per il database abbiamo un volume, quindi possiamo assicurarci che, man mano che il database va su e giù, non perdiamo i dati, quando il contenitore del database si ferma."


Che cosa intendi con "... usa ..." ? E "... transazioni in tutti i possibili millisecondi" ?
Peter Mortensen,

0

Utilizza Persistent Volume Claim (PVC) di Kubernetes, che è uno strumento di gestione e pianificazione dei container Docker:

Volumi persistenti

I vantaggi dell'utilizzo di Kubernetes a questo scopo sono i seguenti:

  • È possibile utilizzare qualsiasi spazio di archiviazione come NFS o altro spazio di archiviazione e anche quando il nodo è inattivo, lo spazio di archiviazione non è necessario.
  • Inoltre, i dati in tali volumi possono essere configurati per essere conservati anche dopo la distruzione del contenitore stesso, in modo che possano essere recuperati, se necessario, da un altro contenitore.
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.