Je perds mes données à la sortie du conteneur

394

Malgré le tutoriel et la FAQ interactifs de Docker, je perds mes données à la sortie du conteneur.

J'ai installé Docker comme décrit ici: http://docs.docker.io/en/latest/installation/ubuntulinux sans aucun problème sur Ubuntu 13.04.

Mais il perd toutes les données à sa sortie.

iman@test:~$ sudo docker version
Client version: 0.6.4 
Go version (client): go1.1.2 
Git commit (client): 2f74b1c 
Server version: 0.6.4 
Git commit (server): 2f74b1c 
Go version (server): go1.1.2 
Last stable version: 0.6.4 


iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:05:47 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu apt-get install ping
Reading package lists... 
Building dependency tree... 
The following NEW packages will be installed: 
  iputils-ping 
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. 
Need to get 56.1 kB of archives. 
After this operation, 143 kB of additional disk space will be used. 
Get:1 http://archive.ubuntu.com/ubuntu/ precise/main iputils-ping amd64 3:20101006-1ubuntu1 [56.1 kB] 
debconf: delaying package configuration, since apt-utils is not installed 
Fetched 56.1 kB in 0s (195 kB/s) 
Selecting previously unselected package iputils-ping. 
(Reading database ... 7545 files and directories currently installed.) 
Unpacking iputils-ping (from .../iputils-ping_3%3a20101006-1ubuntu1_amd64.deb) ... 
Setting up iputils-ping (3:20101006-1ubuntu1) ... 
iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:06:11 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu touch /home/test
iman@test:~$ sudo docker run ubuntu ls /home/test
ls: cannot access /home/test: No such file or directory 

Je l'ai également testé avec des sessions interactives avec le même résultat. Ai-je oublié quelque chose?

EDIT: IMPORTANT POUR LES NOUVEAUX UTILISATEURS DE QUAI

Comme l'ont dit @ mohammed-noureldin et d'autres, ce n'est PAS un conteneur qui sort . Chaque fois, il crée simplement un nouveau conteneur.

iman
la source
10
Cela ne peut pas être appelé " sortie de conteneur ", vous créez simplement un nouveau conteneur, l'utilisation de la sortie de mot peut beaucoup dérouter (j'étais aussi confus à cause de cela).
Mohammed Noureldin
1
@MohammedNoureldin, vous avez raison, sortir n'est pas correct, mais c'est exactement ce que vous, moi et d'autres avons pensé. C'est donc un meilleur mot en question, votre montage fait de la question une réponse! Les nouveaux chercheurs ne trouveront pas ici!
iman
À mon tout début avec Docker, je pensais qu'en fait à cause de VOTRE question, je trouve que l'adresse est simplement FAUX. le nouveau titre a été revu et accepté, je ne comprends pas pourquoi quelqu'un devrait insister sur un mauvais titre, c'est votre question et votre décision.
Mohammed Noureldin
3
Je suis d'accord avec @MohammedNoureldin. La combinaison du titre spécifique, de l'exemple et de la réponse acceptée n'aide pas les futurs lecteurs et surtout les débutants à comprendre Docker. Je proposerais de conserver le titre et la question d'origine, car les débutants chercheront certainement quelque chose comme ça. Mais, pourquoi n'ajoutez-vous pas quelque chose décrivant vos idées fausses au moment où vous avez écrit le post. Cela aidera à clarifier les choses. C'est notre culture ici à SO ... n'est-ce pas? :-)
tgogos
2
J'ai eu ce problème ... chaque fois que vous sortez vous devez démarrer votre conteneur ne pas l'exécuter ... exécuter une image agane créer un nouveau conteneur cela aidera docker à démarrer <id conteneur> docker attacher <id conteneur>
fatemeh

Réponses:

399

Vous devez valider les modifications que vous apportez au conteneur, puis l'exécuter. Essaye ça:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

Obtenez ensuite l'ID du conteneur à l'aide de cette commande:

sudo docker ps -l

Validez les modifications apportées au conteneur:

sudo docker commit <container_id> iman/ping 

Exécutez ensuite le conteneur:

sudo docker run iman/ping ping www.google.com

Cela devrait fonctionner.

Libérer
la source
9
Je devrais donc utiliser commit après chaque exécution pour conserver les données.
iman
5
La validation ne doit être utilisée que lorsque vous effectuez des MODIFICATIONS dans le conteneur (comme l'installation de nouveaux outils ou données) afin que ces modifications soient enregistrées et que la prochaine fois que vous exécuterez un nouveau conteneur à partir de cette image, il commencera à partir du point de la dernière sauvegarde ou commit, en préservant vos données.
Unferth
7
@Unferth que faire si je veux continuer à valider les modifications? Jusqu'à présent, il crée plus d'images avec <none>. Comment puis-je continuer à ajouter la validation au-dessus d'une image existante?
Marconi
62
La validation incrémentielle des modifications n'est pas «la voie du docker». Utilisez un DOCKERFILE.
user2105103
23
Comment vous engagez-vous à l'intérieur du conteneur? Considérez le scénario suivant: 1) J'exécute le conteneur comme ceci: docker run -i -t myimage / bin / bash 2) J'apporte quelques modifications 3) Je ne peux pas valider depuis l'intérieur du conteneur, donc quand je quitte le conteneur, je perdra toutes mes données, sans avoir la possibilité de valider mes modifications précédentes
qgicup
375

Lorsque vous utilisez docker runpour démarrer un conteneur, il crée en fait un nouveau conteneur basé sur l'image que vous avez spécifiée.

Outre les autres réponses utiles ici, notez que vous pouvez redémarrer un conteneur existant après sa fermeture et que vos modifications sont toujours là.

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin
ZeissS
la source
89
docker psvous montre uniquement les conteneurs Docker en cours d'exécution. docker ps -avous montre également ceux qui sont sortis - et que vous pouvez continuer à courir. Une validation n'est nécessaire après chaque exécution que si vous souhaitez y créer un instantané pour une utilisation future, sinon le conteneur lui-même restera pour que vous puissiez continuer à l'utiliser.
user1278519
2
Question s'il vous plaît, donc si je télécharge un jenkinsdocker de serveur et que je l'exécute sur mon hôte ci et qu'il exécute certains travaux que j'ai et, par conséquent, le serveur jenkins écrit sur le disque certains journaux. maintenant, si mon serveur (qui hébergeait mon docker) est redémarré et que je redémarre mon docker jenkins, cela signifierait-il que j'ai perdu tous les fichiers journaux? si c'est le cas, comment puis-je utiliser jenkinsdocker par exemple pour faciliter mon installation jenkins sur CI?
Jas
2
@Jas Si vous vous en tenez au même conteneur et n'en créez pas de nouveaux, il n'y a aucun problème. Docker a de nos jours des politiques de redémarrage, vous pouvez donc le configurer pour redémarrer le même conteneur au redémarrage de la machine. Je vous conseillerais également de mettre votre maison jenkins dans un volume pour pouvoir y accéder de l'extérieur (sauvegardes etc).
ZeissS
7
Voici un moyen pratique de copier des fichiers hors du conteneur une fois que vous quittez:docker cp $(docker ps -alq):/path/to/file .
Josh Habdas
3
vous pouvez également démarrer et attacher un conteneur par son nom. (par exemple docker run -it --name my_debian debianet après docker start my_debian && docker attach my_debian)
Johnny Willer
128

Il existe des façons suivantes de conserver les données de conteneur:

  1. Volumes Docker

  2. Docker commit

    a) créer un conteneur à partir d'une image ubuntu et exécuter un terminal bash.

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b) À l'intérieur du terminal, installez la boucle

       # apt-get update
       # apt-get install curl
    

    c) Sortir du terminal à conteneurs

       # exit
    

    d) Prenez note de votre identifiant de conteneur en exécutant la commande suivante:

       $ docker ps -a
    

    e) enregistrer le conteneur en tant que nouvelle image

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f) vérifiez que vous pouvez voir votre nouvelle image avec curl installé.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
kalyani chaudhari
la source
Faut-il exitavant docker commit? Merci.
Abhishek Anand
2
@AbhishekAnand oui, car avec la docker runcommande, vous exécutez bash dans le conteneur et vous y restez en raison des options -iet -t(interactif avec TTY). Cependant, Docker s'exécute sur votre machine, en dehors du conteneur, donc après avoir apporté les modifications nécessaires au conteneur de l'intérieur, pour revenir au shell de votre système, vous devez exit(ou Ctrl + D) le shell du conteneur. Notez également le #et $dans la réponse, qui indiquent les différents shells dans lesquels les commandes sont écrites.
Erik
Question rapide: si je ne m'engage pas, j'ai perdu les données. C'est clair. Mais quand je change la configuration de nginx, pourquoi reste-t-elle à jour? (pas besoin de s'engager) @Erik
grep
@grep si vous avez un MWE clair et reproductible, veuillez poser une nouvelle question à ce sujet, s'il n'y en a pas déjà un sur ce cas d'utilisation spécifique.
Erik
3. docker stopsuivi de docker start.
carillonateur
59

En plus de la réponse de Unferth , il est recommandé de créer un Dockerfile .

Dans un répertoire vide, créez un fichier appelé "Dockerfile" avec le contenu suivant.

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]

Créez une image à l'aide du Dockerfile . Utilisons une balise pour ne pas avoir à nous souvenir du numéro d'image hexadécimal.

$ docker build -t iman/ping .

Et puis exécutez l'image dans un conteneur.

$ docker run iman/ping stackoverflow.com
salathe
la source
1
Ne jamais avoir à le faire manuellement plus d'une fois est exactement le point de docker. Créez un dockerfile, validez et téléchargez l'image résultante. Tirez ladite image vers l'avant.
Brandon Bertelsen
11

J'ai une réponse beaucoup plus simple à votre question, exécutez les deux commandes suivantes

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a

la commande ps -a ci-dessus renvoie une liste de tous les conteneurs. Prenez le nom du conteneur qui fait référence au nom de l'image - «ubuntu». docker auto génère des noms pour les conteneurs par exemple - 'lightlyxuyzx', c'est si vous n'utilisez pas l'option --name.

Les options -t et -d sont importantes, le conteneur créé est détaché et peut être reconnecté comme indiqué ci-dessous avec l'option -t.

Avec l'option --name, vous pouvez nommer votre conteneur dans mon cas 'mycontainername'.

sudo docker exec -ti mycontainername bash

et cette commande ci-dessus vous aide à vous connecter au conteneur avec bash shell. À partir de ce moment, toutes les modifications que vous apportez dans le conteneur sont automatiquement enregistrées par docker. Par exemple - apt-get install curlà l'intérieur du conteneur Vous pouvez quitter le conteneur sans aucun problème, docker auto enregistre les modifications.

Lors de l'utilisation suivante, il vous suffit d'exécuter ces deux commandes chaque fois que vous souhaitez travailler avec ce conteneur.

Cette commande ci-dessous démarre le conteneur arrêté:

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

Un autre exemple avec des ports et un espace partagé donné ci-dessous:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash

Dans mon cas: 7efe2989e877 - est l'image d'un ancien conteneur en cours d'exécution que j'ai obtenu en utilisant

docker ps -a

Magnus Melwin
la source
4
Avec Docker 18.09.2 sur Ubuntu 18.04, cela ne fonctionne pas tel quel. Cela fonctionne si je mets l' --nameoption et avant le nom de l'image, comme ceci:docker run --name mycontainername -t -d ubuntu /bin/bash
Stéphane Gourichon
9

Vous souhaiterez peut-être consulter les volumes de docker si vous souhaitez conserver les données dans votre conteneur. Visitez https://docs.docker.com/engine/tutorials/dockervolumes/ . La documentation de docker est un très bon point de départ

Kudzanayi Mutamba
la source
3

Ma suggestion est de gérer docker, avec docker compose. Est un moyen facile de gérer tous les conteneurs du docker pour votre projet, vous pouvez mapper les versions et lier différents conteneurs pour travailler ensemble.

Les documents sont très simples à comprendre, mieux que les documents de docker.

Docker-Compose Docs

Meilleur

Cam T
la source
3

Il y a vraiment d'excellentes réponses ci-dessus à la question posée. Il n'est peut-être pas nécessaire d'avoir une autre réponse, mais je veux quand même donner mon opinion personnelle sur le sujet dans les mots les plus simples possibles.

Voici quelques points sur les conteneurs et les images qui nous aideront à conclure:

  • Une image docker peut être :
    1. créé à partir d'un conteneur donné
    2. supprimé
    3. utilisé pour créer n'importe quel nombre de conteneurs
  • Un conteneur docker peut être :
    1. créé à partir d'une image
    2. commencé
    3. arrêté
    4. redémarré
    5. supprimé
    6. utilisé pour créer n'importe quel nombre d'images
  • Une commande d'exécution de docker fait ceci :
    1. Télécharge une image ou utilise une image en cache
    2. Crée un nouveau conteneur à partir de celui-ci
    3. Démarre le conteneur
  • Lorsqu'un Dockerfile est utilisé pour créer une image :
    1. Il est déjà bien connu que l'image sera éventuellement utilisée pour exécuter un conteneur Docker.
    2. Après avoir émis la commande docker build, docker en arrière-plan crée un conteneur en cours d'exécution avec un système de fichiers de base et suit les étapes à l'intérieur du Dockerfile pour configurer ce conteneur selon les besoins des développeurs.
    3. Une fois le conteneur configuré avec les spécifications du Dockerfile, il sera validé en tant qu'image.
    4. L'image se prépare à rock & roll!

Conclusion :

Comme nous pouvons le voir, un conteneur Docker est indépendant d'une image Docker.

Un conteneur peut être redémarré à condition que l'ID unique de ce conteneur [utiliser docker ps --allpour obtenir l'ID] .

Toute opération comme la création d'un nouveau répertoire, la création de fichiers, l'installation d'outils, etc. peut être effectuée à l'intérieur du conteneur lorsqu'il est en cours d'exécution. Une fois le conteneur arrêté, il persiste toutes les modifications. L'arrêt et le redémarrage d'un conteneur est comme le redémarrage d'un système informatique.

Un conteneur déjà créé est toujours disponible pour un redémarrage, mais lorsque nous émettons une docker runcommande, un nouveau conteneur est créé à partir d'une image et, par conséquent, il ressemble à un nouveau système informatique. Les modifications apportées à l'intérieur de l'ancien conteneur - comme nous pouvons le comprendre maintenant - ne sont pas disponibles dans ce nouveau conteneur.

Une note finale :

Je suppose qu'il est maintenant évident pourquoi les données semblent être perdues et pourtant elles sont toujours là .. mais dans un autre [ancien] conteneur. Alors, prenez bonne note de la différence dans docker start& docker runcommand & ne vous y trompez jamais.

Kiran dahibhate
la source
1

le problème similaire (et aucun moyen que Dockerfile puisse résoudre à lui seul) m'a amené à cette page.

étape 0: pour tous, en espérant que Dockerfile pourrait y remédier: jusqu'à ce que --dns et --dns-search apparaissent dans la prise en charge de Dockerfile - il n'y a aucun moyen d'intégrer des ressources intranet dans.

étape 1: après avoir créé l'image à l'aide de Dockerfile (à propos, c'est un grave problème, Dockerfile doit être dans le dossier actuel ), avoir une image pour déployer ce qui est basé sur l'intranet, en exécutant le script d'exécution de docker. exemple: docker run -d \ --dns=${DNSLOCAL} \ --dns=${DNSGLOBAL} \ --dns-search=intranet \ -t pack/bsp \ --name packbsp-cont \ bash -c " \ wget -r --no-parent http://intranet/intranet-content.tar.gz \ tar -xvf intranet-content.tar.gz \ sudo -u ${USERNAME} bash --norc"

étape 2: application du script d'exécution de docker en mode démon fournissant des enregistrements DNS locaux pour pouvoir télécharger et déployer des éléments locaux.

point important: l' exécution du script doit se terminer par quelque chose comme /usr/bin/sudo -u ${USERNAME} bash --norcpour maintenir le conteneur en marche même après la fin des scripts d'installation.

non , il n'est pas possible d'exécuter le conteneur en mode interactif pour toute la question de l'automatisation car il restera à l'intérieur de l'invite de commande interne jusqu'à ce que CTRL-p CTRL-q soit pressé.

non , si l'interaction de bash ne sera pas exécutée à la fin du script d'installation, le conteneur se terminera immédiatement après la fin de l'exécution du script, perdant tous les résultats de l'installation.

étape 3: le conteneur est toujours en cours d'exécution en arrière-plan, mais il n'est pas clair si le conteneur a terminé la procédure d'installation ou pas encore. en utilisant le bloc suivant pour déterminer la fin de la procédure d'exécution: while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done le script continuera plus loin seulement une fois l'installation terminée. et c'est le bon moment pour appeler: commit , en fournissant l'identifiant du conteneur actuel ainsi que le nom de l'image de destination (il peut être le même que sur la procédure de génération / exécution , mais avec la balise de finalisation de l'installation locale. exemple:. docker commit containerID pack/bsp:toolchainedvoir ce lien sur comment obtenir un ID de conteneur approprié

étape 4: le conteneur a été mis à jour avec les installations locales ainsi qu'il a été validé dans l'image nouvellement affectée (celle avec la balise fins ajoutée). il est maintenant sûr d'arrêter le fonctionnement du conteneur. exemple:docker stop packbsp-cont

stage5: à tout moment où le conteneur avec les installations locales doit s'exécuter, démarrez-le avec l'image précédemment enregistrée. exemple:docker run -d -t pack/bsp:toolchained

Oleg Kokorin
la source
1

une brillante réponse ici Comment continuer un docker qui est sorti de l'utilisateur kgs

docker start $(docker ps -a -q --filter "status=exited")
(or in this case just docker start $(docker ps -ql) 'cos you don't want to start all of them)

docker exec -it <container-id> /bin/bash

Cette deuxième ligne est cruciale. Donc, exec est utilisé à la place de run, et non sur une image mais sur un containerid. Et vous le faites après le démarrage du conteneur.

barlop
la source
0

Aucune des réponses ne répond au point de ce choix de conception. Je pense que Docker fonctionne de cette façon pour éviter ces 2 erreurs:

  • Redémarrage répété
  • Erreur partielle
Minh Nghĩa
la source