Compose: Comment `docker-compose up --force-receate` sans réutiliser les volumes précédents

Créé le 2 oct. 2015  ·  23Commentaires  ·  Source: docker/compose

Avec docker-compose 1.4.2 et docker 1.8.2
Vous pouvez voir ci-dessous le premier volume e583c6a8 ... 5a93788a0 est réutilisé

 $ sudo docker-compose up -d --force-recreate
   Recreating remotetransmission_torrent_1...

 $ docker inspect remotetransmission_torrent_1 | grep volumes
   "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data:/home/transmission/.config/transmission-daemon:rw",
   "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data:/home/transmission/Downloads:rw"
   "Source": "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data",
   "Source": "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data",

 $ sudo docker-compose up -d --force-recreate
   Recreating remotetransmission_torrent_1...

 $ docker inspect remotetransmission_torrent_1 | grep volumes
   "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data:/home/transmission/.config/transmission-daemon:rw",
   "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data:/home/transmission/Downloads:rw"
   "Source": "/mnt/docker/volumes/e583c6a87437a5b4b1af50ee2693bd3e5dce574ec72d60dce1311215a93788a0/_data",
   "Source": "/mnt/docker/volumes/cefce79850d7162f4f99541559c2dfc7315c83db717a7a5953118bd3c4b273e0/_data",

Je suis obligé de stop puis rm pour créer de nouveaux volumes

 $ sudo docker-compose stop 
   Stopping remotetransmission_torrent_1... done

 $ sudo docker-compose rm
   Going to remove remotetransmission_torrent_1
   Are you sure? [yN] y
   Removing remotetransmission_torrent_1... done

 $ sudo docker-compose up -d --force-recreate
   Creating remotetransmission_torrent_1...

 $ docker inspect remotetransmission_torrent_1 | grep volumes
   "Source": "/mnt/docker/volumes/c5bb9a8f7b68c762c42e9c0ee92afbca3aa0d7ff9d09aaf45fd260f6fc663ec9/_data",
   "Source": "/mnt/docker/volumes/9dcce8440bafc8893e07352111d1aefb625c36df10da6dc4eaa593220266ea31/_data",

_
Existe-t-il un meilleur moyen que la méthode stop/rm ?

areup kindocs kinquestion

Commentaire le plus utile

Cette stratégie semble enfreindre les meilleures pratiques de docker et nous a causé des tonnes de problèmes de dépannage pour les raisons de la recréation des conteneurs. Quand je dis à docker de recréer, cela ne signifie pas "conserver certaines données dans le conteneur, mais redémarrer les processus dans les conteneurs". Cela signifie paver la terre et recommencer. Si je voulais enregistrer les volumes, je monterais explicitement les volumes. Je ne m'attends jamais à ce que les volumes montés automatiquement de quelque nature que ce soit persistent à travers les exécutions de conteneurs.

Tous les 23 commentaires

stop/rm est la bonne manière. Les données en volume peuvent être importantes, c'est pourquoi nous voulons qu'il soit difficile de les supprimer accidentellement.

Nous pourrions probablement mieux documenter cela.

Cette stratégie semble enfreindre les meilleures pratiques de docker et nous a causé des tonnes de problèmes de dépannage pour les raisons de la recréation des conteneurs. Quand je dis à docker de recréer, cela ne signifie pas "conserver certaines données dans le conteneur, mais redémarrer les processus dans les conteneurs". Cela signifie paver la terre et recommencer. Si je voulais enregistrer les volumes, je monterais explicitement les volumes. Je ne m'attends jamais à ce que les volumes montés automatiquement de quelque nature que ce soit persistent à travers les exécutions de conteneurs.

La persistance des données entre les exécutions est vraiment la seule raison d'utiliser des volumes. Si vous ne voulez pas de données persistantes, pourquoi les mettez-vous dans un volume?

Je ne configure pas de volume. Mon docker-compose.yml n'a pas de configuration de volume et je ne passe rien à docker-compose.yml pour attacher des volumes.

Commander:

docker-compose up --force-recreate --abort-on-container-exit --build foo

docker-compose.yml:

version: '2'
services:
  foo:
    build:
      context: .
      dockerfile: src/integration/foo/Dockerfile
    ports:
      - "3306:3306"
      - "33060:33060"

Dockerfile:

FROM mysql:5.7

COPY schema/foo/migration.sql /data/db_schema.sql
COPY src/integration/foo/create_test_db.sh /docker-entrypoint-initdb.d/create_test_db.sh
ENV MYSQL_ALLOW_EMPTY_PASSWORD true

EXPOSE 3306 33060

create_test_db.sh:

#!/bin/bash
set -e
mysql --no-defaults -u root -e "drop database if exists agent_state; create database foo"
mysql --no-defaults -u root foo < "/data/db_schema.sql"

Si j'exécute ce qui précède, écris des éléments dans la base de données, puis SIG_INT, puis exécutez à nouveau la commande, les données que j'ai placées dans la base de données sont conservées tout au long de la course.

C'est un problème avec l'image MySQL. Il crée un volume dans la base
image. Vous pouvez contourner le problème en utilisant un autre MySQL
image ou éventuellement en le forçant à utiliser un chemin différent pour les données.

Le 19 octobre 2016 à 18h36, "Micah Zoltu" [email protected] a écrit:

Je ne configure pas de volume. Mon docker-compose.yml n'en a pas
configuration des volumes et je ne transmets rien à docker-compose.yml à
attachez tous les volumes.

Commander:

docker-compose up --force-recréer --abort-on-container-exit --build foo

docker-compose.yml:

version 2'
prestations de service:
toto:
construire:
le contexte: .
dockerfile: src / intégration / foo / Dockerfile
ports:
- "3306: 3306"
- "33060: 33060"

Dockerfile:

DE mysql: 5.7

COPY schema / foo / migration.sql /data/db_schema.sql
COPY src / integration / foo / create_test_db.sh /docker-entrypoint-initdb.d/create_test_db.sh
ENV MYSQL_ALLOW_EMPTY_PASSWORD true

EXPOSER 3306 33060

create_test_db.sh:

! / bin / bash

set -e
mysql --no-defaults -u root -e "supprimer la base de données si elle existe agent_state; créer la base de données toto"
mysql --no-defaults -u root toto <"/data/db_schema.sql"

Si j'exécute ce qui précède, écris des trucs dans la base de données, puis SIG_INT, puis exécute le
commande à nouveau les données que j'ai mises dans la base de données sont conservées tout au long de l'exécution.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/docker/compose/issues/2127#issuecomment -254986952,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAa_RG_pJj0i-OSCfcBlG__8ToFDtGKMks5q1sWlgaJpZM4GHruC
.

Hmm, cela viole ma compréhension des conteneurs docker. Comment monter un volume sans que je fournisse un chemin sur l'hôte? Je crois comprendre que les conteneurs docker sont éphémères à moins que vous ne montiez explicitement un volume?

Un volume n'a pas besoin d'un chemin d'hôte. Il existe trois types de volumes:

  • montages de liaison hôte ( -v /host:/container )
  • volumes nommés ( -v name:/container , créés avec docker volume create )
  • volumes anonymes ( -v /container , ou VOLUME dans un Dockerfile )

L'image mysql utilise un volume anonyme. Au moment de l'exécution, vous pouvez indiquer au conteneur d'utiliser un volume différent pour ce chemin dans le conteneur, mais si vous ne le faites pas, le volume anonyme est toujours là.

Les volumes anonymes ne sont pas géniaux. Ils sont les plus anciens des trois, et une grande partie de leur comportement est hérité qui n'est conservé que pour des raisons de compatibilité descendante.

Au moins une option de ligne de commande à la "--recreate-volumes" serait bien ...

OK, les gars, voici le cas auquel penser:

1) Je veux remonter mon répertoire public Rails sur le conteneur nginx, afin que certaines choses statiques puissent être servies directement par nginx.
2) J'attribue un volume "anonyme" (non monté sur l'hôte, non nommé) à / usr / local / app / app / public, et le partage avec nginx via "volumes_from"
3) le contenu "public" est souvent modifié sur les builds d'image - non seulement les fichiers de niveau supérieur mais certains fichiers dans les sous-répertoires (c'est important)

Actuellement, si je recrée des conteneurs, je me retrouve avec une ancienne version de "public" - le contenu de l'image est simplement ignoré. Oui, Docker est censé copier les fichiers

Donc, je suis soit obligé d'exécuter une séquence "stop-rm-up" (pas si pratique en production), soit d'utiliser un répertoire séparé comme volume partagé, et d'appeler explicitement 'rsync' sur le début du conteneur d'application pour le remplir / le mettre à jour.

S'il y avait un moyen de laisser simplement le volume anonyme aller avec le conteneur parent, ce serait une grande amélioration.

N'utilisez pas de volumes pour le code (ou les actifs statiques). Les volumes concernent les données que vous souhaitez conserver entre les déploiements, ce qui est le contraire de ce que vous souhaitez ici. Créez l'image nginx avec les actifs statiques ou créez un proxy pour un conteneur de serveur Web qui les contient.

Merci pour le point de vue! Je n'ai pas encore pensé dans cette perspective.

Cela semble être l'un des problèmes conceptuels de l'architecture Docker (toujours en évolution). Nous avons vu l'évolution du concept des volumes de données jusqu'à présent (par exemple, des «conteneurs de données» aux «volumes nommés») et ce n'est probablement pas encore terminé.

Si vous regardez https://docs.docker.com/engine/tutorials/dockervolumes/#/data -volumes, vous verrez que la plupart des avantages décrits (contournement AUFS, partage) ne sont pas nécessairement liés à la persistance des données ( pour quels volumes ont été initialement conçus).

Il n'est donc pas surprenant que les gens (moi y compris) essaient d'utiliser les volumes de différentes manières au-delà de leur objectif initial. Par exemple, pour partager des données éphémères ou contrôlées par image d'un conteneur à un autre, sans beaucoup de copie explicite.

Peut-être qu'un jour nous trouverons la manière standard cohérente de le faire. :) Jusqu'à présent, il est possible d'utiliser des solutions de contournement assez simples décrites ci-dessus. Pas idéal, mais acceptable, tant que les attentes architecturales sont correctement définies.

Encore une fois, merci pour votre réponse, clarification et pour l'excellent travail que vous faites!

Je suis tombé sur ce problème aujourd'hui, merci pour les excellentes explications ici, tout le monde m'a certainement aidé à comprendre le problème.

Un point de confusion majeur pour moi était de comprendre que la balise VOLUME dans un fichier dockerfile provoquait la création d'un volume anonyme cohérent. Je l'ai peut-être manqué dans la documentation, mais je n'ai pas trouvé de mention à ce sujet.

@dnephin

Comme mentionné @ hleb-rubanau. Exécuter un seul conteneur avec Rails et Nginx est la solution? (Comme ceci: https://docs.docker.com/engine/admin/multi-service_container/?)

Dois-je enfreindre les meilleures pratiques ("Chaque conteneur ne doit avoir qu'une seule préoccupation
") uniquement pour les éléments de diffusion? :(

Pour les personnes intéressées, je me suis retrouvé avec ce qui suit:

1) Dans mes configurations, j'utilise toujours des volumes montés en liaison (aka montés sur l'hôte) maintenant. Les volumes anonymes et nommés ont trop de logique spéciale / non évidente / conditionnelle / incohérente / impicite à prendre en compte. Oui, il est facile de comprendre les spécificités du cycle de vie et de la gestion de chaque type, mais j'ai trouvé qu'il était plus facile pour moi de penser à l'architecture lorsque je ne suis pas préoccupé par toutes ces différences non pertinentes. Pour FS distribué, Gluster fonctionne correctement (toujours monté en liaison depuis la perspective Docker).

2) Le volume partagé est un volume monté en liaison et ce n'est pas le répertoire dans lequel les actifs sont stockés dans l'image. Au début (au point d'entrée), j'exécute rsync local, de sorte que les actifs du répertoire de l'image soient copiés / synchronisés sur le chemin de stockage partagé monté sur la liaison.

Merci @ hleb-rubanau

Quoi qu'il en soit, je ne suis pas sûr que certains outils d'orchestration comme RancherOS prennent en charge ces configurations de volume ou soient le bon moyen pour évoluer. A la fin, c'est plus difficile de déployer avec docker ...

Je préfère utiliser des volumes anonymes et nettoyer les orphelins à un moment donné.

Voici ma pile de rails de production: https://github.com/brunocascio/AR-MTB/blob/master/docker-compose.prod.yml

Cela m'a également causé une grande confusion lorsque je testais l'image jenkins / jenkins et que cela ne respectait pas mes modifications des fichiers dans / usr / share / jenkins / ref car il les avait déjà copiés.

C'est une expérience utilisateur assez inattendue - docker compose crée un volume "caché" à toutes fins utiles. Si vous utilisez docker run normal, vous obtenez un nouveau volume à chaque fois. C'est un volume caché dans le sens où rien dans le docker-compose up n'en parle, donc à moins que vous ne sachiez en détail ce que fait l'image, vous devez aller creuser.

Au moins, nous devrions imprimer un message disant "ne pas recréer le volume x" afin que d'autres personnes à l'avenir n'aient pas à perdre de temps à se demander ce qui se passe.

Salut @dnephin ,

J'appelle sudo rm -rf /var/lib/docker/volumes/aa_dbdatavol et maintenant je ne peux plus docker-compose up my postgres docker-compose .

Obtenir cette erreur

Création du réseau "aa_default" avec le pilote par défaut
Création de aa_postgres_1
ERREUR: pour postgres Impossible de créer un conteneur pour le service postgres: aucun fichier ou répertoire de ce type
ERREUR: erreurs rencontrées lors de la mise en place du projet.
Réponse d'erreur du démon: aucun conteneur de ce type: aa_postgres_1

Comme vous avez peut-être une idée pour contourner cela, partagez-la. Je vous remercie!

https://github.com/docker/compose/issues/2127#issuecomment -347152650

Le simple fait de recréer le dossier résoudra mon problème.
/var/lib/docker/volumes/aa_dbdatavol/_data

Un grand merci à @dnephin , votre réponse a parfaitement fonctionné, la première fois. Muchos gracias.

@dnephin a dit:

La persistance des données entre les exécutions est vraiment la seule raison d'utiliser des volumes. Si vous ne voulez pas de données persistantes, pourquoi les mettez-vous dans un volume?

pour partager des fichiers entre conteneurs. Existe-t-il une meilleure façon de faire cela sans utiliser de volumes?

Qu'entendez-vous par «partager des fichiers»?

Vous attendez-vous à ce qu'un conteneur écrira dans un fichier et que l'autre conteneur verra ces écritures? Un système de fichiers n'est généralement pas une bonne interface entre deux services, mais si tel est le cas, vous pouvez demander à l'un des services de "gérer" le système de fichiers en écrivant des mises à jour sur le volume.

Si le "partage" signifie simplement que deux conteneurs lisent certains des mêmes fichiers, alors il n'y a pas besoin d'un volume. Ajoutez le fichier aux deux conteneurs avec COPY .

J'utilise Docker version 18.06.1-ce, build e68fc7a et je peux utiliser la commande suivante pour recréer des volumes anonymes:

docker-compose up -d --build --force-recreate --renew-anon-volumes db

Il semble que le drapeau --renew-anon-volumes ait été ajouté récemment

J'utilise Docker version 18.06.1-ce, build e68fc7a et je peux utiliser la commande suivante pour recréer des volumes anonymes:

docker-compose up -d --build --force-recreate --renew-anon-volumes db

Il semble que le drapeau --renew-anon-volumes ait été ajouté récemment

Merci d'avoir laissé cette option.

Cette page vous a été utile?
0 / 5 - 0 notes