¿Cómo mover contenedores Docker entre diferentes hosts?

98

No puedo encontrar una forma de mover contenedores en ejecución Docker de un host a otro.

¿Hay alguna forma de que pueda enviar mis contenedores a repositorios como lo hacemos con las imágenes? Actualmente, no estoy usando volúmenes de datos para almacenar los datos asociados con aplicaciones que se ejecutan dentro de contenedores. Entonces, algunos datos residen dentro de los contenedores, que quiero conservar antes de rediseñar la configuración.

Dinesh Reddy
fuente
Eche un vistazo a flocker github.com/ClusterHQ/flocker
Adrian Mouat
Tenga en cuenta que es posible que desee utilizar guardar / cargar en lugar de exportar / importar, ya que guardar conserva los metadatos y el historial.
Burstaholic
¿Debería ser este un comentario a la respuesta de @ aholt?
Martin Thompson
docker savees para guardar imágenes, no contenedores. docs.docker.com/engine/reference/commandline/save
stmllr

Respuestas:

57

No puede mover un contenedor Docker en ejecución de un host a otro.

Puede confirmar los cambios en su contenedor a una imagen con docker commit, mover la imagen a un nuevo host y luego comenzar un nuevo contenedor condocker run . Esto conservará los datos que su aplicación haya creado dentro del contenedor.

Nb: no conserva los datos que se almacenan dentro de los volúmenes; necesita mover los volúmenes de datos manualmente a un nuevo host.

larsks
fuente
@larsks ¿No sería el primer paso detener el contenedor y luego realizar la confirmación?
valentt
@valentt Ambos son posibles, para confirmar el contenedor en ejecución y detenido
crollywood
1
Esta respuesta realmente no explica exactamente los comandos que necesita usar, lo que lo hace difícil para un novato como yo
Paul Kruger
docker-checkpoint podría permitirle mover un contenedor "en ejecución" entre hosts, si ambos admiten CRIU.
dGRAMOP
2
1. detenga el contenedor docker stop x; 2. cometer cambios ur docker commit -p x x; 3. guarde el contenedor en la imagen docker save -o x x; 4. mueva el archivo x al nuevo host y en el nuevo host cargue la nueva imagen dokcer load -i x(si inició el contenedor con la -vopción, también tendrá que mover estos archivos al nuevo host); 5. ejecute esta imagen condocker run (-v is required to mount these files if needed)
Lau Real
95

Alternativamente, si no desea enviar a un repositorio:

  1. Exportar el contenedor a un tarball

    docker export <CONTAINER ID> > /home/export.tar
    
  2. Mueva su tarball a una nueva máquina

  3. Importarlo de nuevo

    cat /home/export.tar | docker import - some-name:latest
    
aholt
fuente
8
Además, no conserva los datos que se almacenan dentro de los volúmenes.
stmllr
1
¿Cómo se supone que esto funcione? Después de la importación obtengo una nueva imagen, ¿y luego qué? ¿Solo hacer un nuevo comando de ejecución?
valentt
2
En realidad, esta es una sugerencia realmente mala, especialmente para los contenedores que ejecutan la base de datos. Probé esta sugerencia y no funcionó. ¿Podría funcionar con detener el contenedor primero?
valentt
2
Esta sugerencia solo fue realmente una alternativa. Puede que funcione para su situación, puede que no. En mi caso, en ese momento estaba configurando contenedores de la ventana acoplable de replicación de la base de datos, y para la exportación / importación, no me importaba conservar los datos, ya que estaba ejecutando copias de seguridad de los datos de la base de datos regularmente en un tarball diferente. Por eso, esto funcionó perfectamente.
aholt
32

Lo que finalmente funcionó para mí, después de muchos manuales confusos y tutoriales confusos, ya que Docker obviamente está en el momento de escribir mi artículo en un punto de expectativas infladas , es:

  1. Guarde la imagen de la ventana acoplable en un archivo:
    docker save image_name > image_name.tar
  2. copiar en otra máquina
  3. en esa otra máquina acoplable, ejecute docker load de la siguiente manera:
    cat image_name.tar | docker load

Exportar e importar, como se propone en otras respuestas, no exporta puertos y variables, que podrían ser necesarios para que su contenedor se ejecute. Y puede terminar con cosas como "Sin comando especificado", etc. Cuando intente cargarlo en otra máquina.

Entonces, la diferencia entre guardar y exportar es que el comando de guardar guarda la imagen completa con historial y metadatos, mientras que el comando de exportación exporta solo la estructura de archivos (sin historial ni metadatos).

No hace falta decir que, si ya tiene esos puertos tomados en el hipervisor de la ventana acoplable que está importando, por algún otro contenedor de la ventana acoplable, terminará en conflicto y tendrá que reconfigurar los puertos expuestos.

Aleksandar Pavić
fuente
1
Muy útil. El mensaje "Sin comando especificado" me estaba volviendo loco.
Rintoul
El mensaje "Sin comando especificado" también me estaba volviendo loco. Yo uso docker commit <container-id> stackstorm-local: 2.9, y docker pull stackstorm-local: 2.9 de otro host.
Hua Zhang
18

De la documentación de Docker:

docker exportno exporta el contenido de los volúmenes asociados con el contenedor. Si un volumen está montado sobre un directorio existente en el contenedor, docker exportexportará el contenido del directorio subyacente , no el contenido del volumen. Consulte Copia de seguridad, restauración o migración de volúmenes de datos en la guía del usuario para obtener ejemplos sobre la exportación de datos en un volumen.

Antonio De Marinis
fuente
cluster hq shutdown ... y BTW para migrar el contenedor, el contenedor debe ejecutarse en ZFS / cualquier lun de almacenamiento admitido
asvignesh
6

Utilice este script: https://github.com/ricardobranco777/docker-volumes.sh

Esto hace conservar los datos en los volúmenes.

Uso de ejemplo:

# 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
fuente
1
No funcionó para mí en AWS Linux (Centos). Al final, tomé el enfoque de baja tecnología de usar docker inspect para encontrar el directorio de volumen y luego copiarlo manualmente.
JasonPlutext
@JasonPlutext ¿Quizás algo relacionado con SELinux? ¿Tiene SELinux habilitado?
Ricardo Branco
1

Probé muchas soluciones para esto, y esta es la que funcionó para mí:

Confirmar / guardar el contenedor en una nueva imagen:

  1. ++ confirmar el contenedor:
    # docker stop
    # docker commit CONTAINER_NAME
    # docker save --output IMAGE_NAME.tar IMAGE_NAME: TAG


ps: "Nuestro contenedor CONTAINER_NAME tiene un volumen montado en '/ var / home'" (debe inspeccionar su contenedor para especificar su ruta de volumen: # docker inspect CONTAINER_NAME)

  1. ++ guardar su volumen: usaremos una imagen de ubuntu para hacer la cosa.
    # 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”.

Ahora, cuando mire $ {pwd} / backup, encontrará nuestro volumen en formato tar.
Hasta ahora, tenemos la imagen de nuestro contenedor 'IMAGE_NAME.tar' y su volumen 'volume_backup.tar'.

Ahora puede volver a crear el mismo contenedor antiguo en un nuevo host.

Houssam Ezzoukh
fuente