Comment déplacer des conteneurs Docker entre différents hôtes?

98

Je ne trouve pas de moyen de déplacer les conteneurs exécutant le docker d'un hôte à un autre.

Existe-t-il un moyen de pousser mes conteneurs vers des référentiels comme nous le faisons pour les images? Actuellement, je n'utilise pas de volumes de données pour stocker les données associées aux applications exécutées dans des conteneurs. Ainsi, certaines données résident dans des conteneurs, que je souhaite conserver avant de redéfinir la configuration.

Dinesh Reddy
la source
Jetez un œil à flocker github.com/ClusterHQ/flocker
Adrian Mouat
Notez que vous souhaiterez peut-être utiliser save / load au lieu d'export / import, car save préserve les métadonnées et l'historique.
Burstaholic
Cela devrait-il être un commentaire à la réponse de @ aholt?
Martin Thompson
docker savesert à enregistrer des images, pas des conteneurs. docs.docker.com/engine/reference/commandline/save
stmllr

Réponses:

57

Vous ne pouvez pas déplacer un conteneur Docker en cours d'exécution d'un hôte à un autre.

Vous pouvez valider les modifications de votre conteneur dans une image avec docker commit, déplacer l'image sur un nouvel hôte, puis démarrer un nouveau conteneur avec docker run. Cela conservera toutes les données créées par votre application à l'intérieur du conteneur.

Nb: il ne conserve pas les données stockées dans des volumes; vous devez déplacer manuellement les volumes de données vers un nouvel hôte.

larsks
la source
@larsks La première étape ne serait-elle pas d'arrêter le conteneur, puis de faire la validation?
valentt
@valentt Les deux sont possibles, pour valider le conteneur en cours d'exécution et arrêté
crollywood
1
Cette réponse n'explique pas vraiment exactement les commandes que vous devez utiliser, ce qui rend la tâche difficile pour un noob comme moi
Paul Kruger
docker-checkpoint pourrait vous permettre de déplacer un conteneur "en cours d'exécution" entre les hôtes, s'ils prennent tous deux en charge CRIU.
dGRAMOP
2
1. arrêtez le conteneur docker stop x; 2. commettez vos changements docker commit -p x x; 3. enregistrez le conteneur dans l'image docker save -o x x; 4. déplacez le fichier x vers le nouvel hôte et dans le nouvel hôte, chargez la nouvelle image dokcer load -i x(si vous -vdémarrez le conteneur avec l' option, vous devrez également déplacer ces fichiers vers le nouvel hôte); 5. exécuter cette image avecdocker run (-v is required to mount these files if needed)
Lau Real
95

Sinon, si vous ne souhaitez pas pousser vers un référentiel:

  1. Exporter le conteneur vers une archive tar

    docker export <CONTAINER ID> > /home/export.tar
    
  2. Déplacez votre archive sur une nouvelle machine

  3. Importez-le

    cat /home/export.tar | docker import - some-name:latest
    
aholt
la source
8
Ne conserve pas non plus les données stockées dans des volumes.
stmllr
1
Comment cela fonctionne-t-il? Après l'importation, j'obtiens une nouvelle image, et puis quoi? Juste faire une nouvelle commande d'exécution?
valentt
2
C'est en fait une très mauvaise suggestion, en particulier pour les conteneurs exécutant la base de données. J'ai essayé cette suggestion et cela n'a pas fonctionné. Cela pourrait-il fonctionner avec l'arrêt du conteneur en premier?
valentt
2
Cette suggestion n'était vraiment destinée qu'à une alternative. Cela pourrait fonctionner pour votre situation, mais peut-être pas. Pour moi, je mettais en place des conteneurs de docker de réplication de base de données à l'époque, et pour l'exportation / importation, je ne me souciais pas de préserver les données, car j'exécutais régulièrement des sauvegardes des données de la base de données sur une autre archive tar. Pour cela, cela a parfaitement fonctionné.
aholt le
32

Ce qui a finalement fonctionné pour moi, après beaucoup de manuels déroutants et de didacticiels déroutants, puisque Docker est évidemment au moment de ma rédaction à un aperçu des attentes exagérées , c'est:

  1. Enregistrez l'image du docker dans l'archive:
    docker save image_name > image_name.tar
  2. copier sur une autre machine
  3. sur cette autre machine docker, exécutez docker load de la manière suivante:
    cat image_name.tar | docker load

L'exportation et l'importation, comme proposé dans une autre réponse, n'exporte pas les ports et les variables, qui peuvent être nécessaires à l'exécution de votre conteneur. Et vous pourriez vous retrouver avec des trucs comme "Aucune commande spécifiée" etc ... Lorsque vous essayez de le charger sur une autre machine.

Ainsi, la différence entre enregistrer et exporter est que la commande save enregistre l'image entière avec l'historique et les métadonnées, tandis que la commande d'exportation exporte uniquement la structure des fichiers (sans historique ni métadonnées).

Inutile de dire que si vous avez déjà pris ces ports sur l'hyper-viseur docker que vous importez, par un autre conteneur docker, vous vous retrouverez en conflit et vous devrez reconfigurer les ports exposés.

Aleksandar Pavić
la source
1
Très utile. Le message "Aucune commande spécifiée" me rendait fou.
Rintoul
Le message "Aucune commande spécifiée" me rendait fou aussi. J'utilise docker commit <container-id> stackstorm-local: 2.9 et docker pull stackstorm-local: 2.9 d'un autre hôte.
Hua Zhang
18

À partir de la documentation Docker:

docker exportn'exporte pas le contenu des volumes associés au conteneur. Si un volume est monté au-dessus d'un répertoire existant dans le conteneur, docker exportexportera le contenu du répertoire sous - jacent , pas le contenu du volume. Reportez-vous à Sauvegarder, restaurer ou migrer des volumes de données dans le guide de l'utilisateur pour obtenir des exemples sur l'exportation de données dans un volume.

Antonio De Marinis
la source
arrêt du siège du cluster ... et BTW pour migrer le conteneur, le conteneur doit s'exécuter sur ZFS / tout lun de stockage pris en charge
asvignesh
6

Utilisez ce script: https://github.com/ricardobranco777/docker-volumes.sh

Cela fait conserver les données en volumes.

Exemple d'utilisation:

# Stop the container   
docker stop $CONTAINER

# Create a new image   
docker commit $CONTAINER $CONTAINER

# Save image
docker save -o $CONTAINER.tar $CONTAINER

# Save the volumes (use ".tar.gz" if you want compression)
docker-volumes.sh $CONTAINER save $CONTAINER-volumes.tar

# Copy image and volumes to another host
scp $CONTAINER.tar $CONTAINER-volumes.tar $USER@$HOST:

# On the other host:
docker load -i $CONTAINER.tar
docker create --name $CONTAINER [<PREVIOUS CONTAINER OPTIONS>] $CONTAINER

# Load the volumes
docker-volumes.sh $CONTAINER load $CONTAINER-volumes.tar

# Start container
docker start $CONTAINER
Ricardo Branco
la source
1
Cela n'a pas fonctionné pour moi sur AWS Linux (Centos). En fin de compte, j'ai adopté l'approche low-tech consistant à utiliser docker inspect pour trouver le répertoire du volume, puis à le copier manuellement.
JasonPlutext
@JasonPlutext Peut-être quelque chose lié à SELinux? Avez-vous activé SELinux?
Ricardo Branco
Got this: tar: Suppression du premier `/ 'des noms de membres
hjahan
1

J'ai essayé de nombreuses solutions pour cela, et c'est celle qui a fonctionné pour moi:

1. valider / enregistrer le conteneur dans une nouvelle image:

  1. ++ valider le conteneur:
    # docker stop
    # docker commit CONTAINER_NAME
    # docker save --output IMAGE_NAME.tar IMAGE_NAME: TAG


ps: "Notre conteneur CONTAINER_NAME a un volume monté sur '/ var / home'" (vous devez inspecter votre conteneur pour spécifier son chemin de volume: # docker inspect CONTAINER_NAME)

  1. ++ enregistrer son volume: nous utiliserons une image ubuntu pour faire la chose.
    # mkdir backup
    # docker run --rm --volumes-from CONTAINER_NAME -v $ {pwd} / backup: / backup ubuntu bash -c "cd / var / home && tar cvf /backup/volume_backup.tar."

Maintenant, quand vous regardez $ {pwd} / backup, vous trouverez notre volume au format tar.
Jusqu'à présent, nous avons l'image de notre conatainer 'IMAGE_NAME.tar' et son volume 'volume_backup.tar'.

Vous pouvez maintenant recréer le même ancien conteneur sur un nouvel hôte.

Houssam Ezzoukh
la source