Pierdo mis datos cuando el contenedor sale

394

A pesar del tutorial interactivo y las preguntas frecuentes de Docker, pierdo mis datos cuando sale el contenedor.

He instalado Docker como se describe aquí: http://docs.docker.io/en/latest/installation/ubuntulinux sin ningún problema en ubuntu 13.04.

Pero pierde todos los datos cuando sale.

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 

También lo probé con sesiones interactivas con el mismo resultado. ¿Olvidé algo?

EDITAR: IMPORTANTE PARA NUEVOS USUARIOS DE DOCKER

Como @ mohammed-noureldin y otros dijeron, en realidad esto NO es un contenedor que sale . Cada vez solo crea un nuevo contenedor.

iman
fuente
10
Eso no se puede llamar " salida de contenedor ", solo está creando un nuevo contenedor, el uso de la palabra de salida puede confundir mucho (también estaba confundido por eso).
Mohammed Noureldin
1
@MohammedNoureldin, tienes razón, salir no es correcto, pero esto es exactamente lo que tú, yo y otros pensamos. Así que es una mejor palabra en cuestión, ¡tu edición hace que la pregunta sea una respuesta! ¡Los nuevos buscadores no encontrarán aquí!
Iman
En mi punto de partida con Docker, pensé que en realidad debido a SU pregunta, encuentro que la dirección es simplemente INCORRECTA. el nuevo título fue revisado y aceptado, no entiendo por qué alguien debería insistir en un título incorrecto, es su pregunta y su decisión.
Mohammed Noureldin
3
Estoy de acuerdo con @MohammedNoureldin. La combinación del título específico, el ejemplo y la respuesta aceptada no ayuda a los futuros lectores y especialmente a los principiantes a comprender Docker. Propondría mantener el título y la pregunta original, ya que los principiantes definitivamente buscarán algo como esto. Pero, ¿por qué no agrega algo que describa sus ideas falsas en el momento en que escribió la publicación? Ayudará a aclarar las cosas. Esta es nuestra cultura aquí en SO ... ¿no? :-)
tgogos
2
Tuve este problema ... cada vez que salgas tienes que iniciar tu contenedor, no ejecutarlo ... ejecuta una nueva imagen crea un nuevo contenedor, esto ayudará a Docker a iniciar <id del contenedor> docker attach <id del contenedor>
fatemeh

Respuestas:

399

Debe confirmar los cambios que realiza en el contenedor y luego ejecutarlo. Prueba esto:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

Luego obtenga la identificación del contenedor con este comando:

sudo docker ps -l

Confirmar cambios en el contenedor:

sudo docker commit <container_id> iman/ping 

Luego ejecute el contenedor:

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

Esto debería funcionar.

Unferth
fuente
99
Entonces debería usar commit después de cada ejecución para preservar los datos.
Iman
55
La confirmación debe usarse solo cuando realice CAMBIOS en el contenedor (como instalar nuevas herramientas o datos) para que esos cambios se guarden y la próxima vez que ejecute un nuevo contenedor desde esa Imagen, comenzará desde el último punto de guardado o comprometerse, preservando sus datos.
Unferth
77
@Unferth ¿qué pasa si quiero seguir confirmando cambios? Hasta ahora crea más imágenes con <none>. ¿Cómo sigo agregando el commit encima de una imagen existente?
Marconi
6262
La confirmación gradual de los cambios no es "la manera del acoplador". Use un DOCKERFILE.
user2105103
23
¿Cómo se comprometería desde dentro del contenedor? Considere el siguiente escenario: 1) Estoy ejecutando el contenedor de esta manera: docker run -i -t myimage / bin / bash 2) Realizo algunos cambios 3) No puedo confirmar desde dentro del contenedor, así que cuando salgo del contenedor, perderá todos mis datos, sin tener la oportunidad de confirmar mis cambios anteriores
qgicup
375

Cuando utiliza docker runpara iniciar un contenedor, en realidad crea un nuevo contenedor basado en la imagen que ha especificado.

Además de las otras respuestas útiles aquí, tenga en cuenta que puede reiniciar un contenedor existente después de que salga y sus cambios aún estén allí.

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin
ZeissS
fuente
89
docker psmuestra que solo está ejecutando contenedores acoplables. docker ps -atambién te muestra los que han salido, y que puedes seguir corriendo. Una confirmación solo es necesaria después de cada ejecución si desea hacer una instantánea allí para su uso futuro, de lo contrario, el contenedor se quedará para que pueda seguir usándolo.
user1278519
2
Pregunta por favor, así que si descargo un jenkinsacoplador de servidor y lo ejecuto en mi host ci y ejecuta algunos trabajos que tengo y, como resultado, el servidor jenkins escribe en el disco algunos registros. ahora si mi servidor (que alojaba mi docker) se reinicia y vuelvo a iniciar mi docker jenkins, ¿significaría que perdí todos los archivos de registro? si es así, ¿cómo puedo usar jenkinsdocker, por ejemplo, para facilitar mi instalación de jenkins en CI?
Jas
2
@Jas Si te quedas en el mismo contenedor y no creas nuevos, no hay problemas. Docker hoy en día tiene políticas de reinicio, por lo que puede configurarlo para reiniciar el mismo contenedor en el reinicio de la máquina. También le aconsejaría que coloque su hogar jenkins en un volumen para poder acceder a él desde el exterior (copias de seguridad, etc.).
ZeissS
77
Aquí hay una forma práctica de copiar archivos del contenedor una vez que salga:docker cp $(docker ps -alq):/path/to/file .
Josh Habdas
3
También puede iniciar y adjuntar un contenedor por su nombre. (por ejemplo docker run -it --name my_debian debiany después docker start my_debian && docker attach my_debian)
Johnny Willer
128

Existen las siguientes formas de conservar los datos del contenedor:

  1. Volúmenes Docker

  2. Docker commit

    a) crear contenedor desde la imagen de ubuntu y ejecutar un terminal bash.

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

    b) Dentro del terminal, instale el rizo

       # apt-get update
       # apt-get install curl
    

    c) Salga de la terminal de contenedores

       # exit
    

    d) Tome nota de su ID de contenedor ejecutando el siguiente comando:

       $ docker ps -a
    

    e) guardar contenedor como nueva imagen

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

    f) verifique que puede ver su nueva imagen con curl instalado.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
kalyani chaudhari
fuente
¿Es necesario exitantes docker commit? Gracias.
Abhishek Anand
2
@AbhishekAnand sí, porque con el docker runcomando ejecutas bash en el contenedor y te quedas allí debido a las opciones -iy -t(interactivas con TTY). Sin embargo, Docker se ejecuta en su máquina, fuera del contenedor, por lo que después de realizar los cambios necesarios en el contenedor desde el interior, para volver al shell de su sistema, debe exit(o Ctrl + D) el shell del contenedor. También tenga en cuenta el #y $en la respuesta, que indica los diferentes shells en los que se escriben los comandos.
Erik
Pregunta rápida: si no me comprometo, pierdo los datos. Está vacío. Pero cuando cambio la configuración de nginx, ¿por qué permanece actualizado? (no es necesario comprometerse) @Erik
grep
@grep si tiene un MWE claro y reproducible, haga una nueva pregunta al respecto, si todavía no hay uno sobre este caso de uso específico.
Erik
3. docker stopseguido de docker start.
carillonador
59

Además de la respuesta de Unferth , se recomienda crear un Dockerfile .

En un directorio vacío, cree un archivo llamado "Dockerfile" con el siguiente contenido.

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

Crea una imagen usando el Dockerfile . Usemos una etiqueta para no tener que recordar el número de imagen hexadecimal.

$ docker build -t iman/ping .

Y luego ejecute la imagen en un contenedor.

$ docker run iman/ping stackoverflow.com
salathe
fuente
1
Nunca tener que hacerlo manualmente más de una vez es exactamente el objetivo de la ventana acoplable. Cree un dockerfile, confirme y cargue la imagen resultante. Tire de dicha imagen hacia adelante.
Brandon Bertelsen
11

Tengo una respuesta mucho más simple a su pregunta, ejecute los siguientes dos comandos

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

El comando ps -a anterior devuelve una lista de todos los contenedores. Tome el nombre del contenedor que hace referencia al nombre de la imagen: 'ubuntu'. docker genera automáticamente nombres para los contenedores, por ejemplo 'lightlyxuyzx', si no usa la opción --name.

Las opciones -t y -d son importantes, el contenedor creado se separa y se puede volver a conectar como se indica a continuación con la opción -t.

Con la opción --name, puede nombrar su contenedor en mi caso 'mycontainername'.

sudo docker exec -ti mycontainername bash

y este comando anterior le ayuda a iniciar sesión en el contenedor con bash shell. A partir de este momento, Docker guarda automáticamente cualquier cambio que realice en el contenedor. Por ejemplo, apt-get install curldentro del contenedor Puede salir del contenedor sin problemas, Docker guarda automáticamente los cambios.

En el próximo uso, todo lo que tiene que hacer es ejecutar estos dos comandos cada vez que quiera trabajar con este contenedor.

El siguiente comando iniciará el contenedor detenido:

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

Otro ejemplo con puertos y un espacio compartido a continuación:

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

En mi caso: 7efe2989e877 - es la imagen de un contenedor anterior en ejecución que obtuve usando

docker ps -a

Magnus Melwin
fuente
44
Con Docker 18.09.2 en Ubuntu 18.04 no funciona como está. Funciona si pongo la --nameopción y antes del nombre de la imagen, así:docker run --name mycontainername -t -d ubuntu /bin/bash
Stéphane Gourichon
3

Mi sugerencia es administrar docker, con docker compose. Es una manera fácil de administrar todos los contenedores de Docker para su proyecto, puede asignar las versiones y vincular diferentes contenedores para trabajar juntos.

Los documentos son muy simples de entender, mejor que los documentos de Docker.

Docker-Compose Docs

Mejor

Cam T
fuente
3

Hay realmente excelentes respuestas a la pregunta anterior. Puede que no haya necesidad de otra respuesta, pero aun así quiero dar mi opinión personal sobre el tema en las palabras más simples posibles.

Aquí hay algunos puntos sobre contenedores e imágenes que nos ayudarán a llegar a una conclusión:

  • Una imagen acoplable puede ser :
    1. creado a partir de un contenedor dado
    2. eliminado
    3. usado para crear cualquier número de contenedores
  • Un contenedor acoplable puede ser :
    1. creado a partir de una imagen
    2. empezado
    3. detenido
    4. reiniciado
    5. eliminado
    6. solía-crear-cualquier-número-de-imágenes
  • Un comando de ejecución de Docker hace esto :
    1. Descarga una imagen o usa una imagen en caché
    2. Crea un nuevo contenedor a partir de él
    3. Inicia el contenedor.
  • Cuando se utiliza un Dockerfile para crear una imagen :
    1. Ya es bien sabido que la imagen finalmente se utilizará para ejecutar un contenedor acoplable.
    2. Después de emitir el comando docker build, docker detrás de escena crea un contenedor en ejecución con un sistema de archivos base y sigue los pasos dentro del Dockerfile para configurar ese contenedor según lo necesiten los desarrolladores.
    3. Después de configurar el contenedor con las especificaciones del Dockerfile, se confirmará como una imagen.
    4. ¡La imagen se prepara para el rock & roll!

conclusión :

Como podemos ver, un contenedor acoplable es independiente de una imagen acoplable.

Se puede reiniciar un contenedor siempre que la ID única de ese contenedor [se use docker ps --allpara obtener la identificación] .

Cualquier operación como crear un nuevo directorio, crear archivos, instalar herramientas, etc. se puede hacer dentro del contenedor cuando se está ejecutando. Una vez que se detiene el contenedor, persiste todos los cambios. La detención y el reinicio del contenedor es como reiniciar un sistema informático.

Un contenedor ya creado siempre está disponible para reiniciar, pero cuando emitimos un docker runcomando, se crea un nuevo contenedor a partir de una imagen y, por lo tanto, es como un nuevo sistema informático. Los cambios realizados dentro del contenedor anterior, como podemos entender ahora, no están disponibles en este nuevo contenedor.

Una nota final :

Supongo que ahora es obvio por qué los datos parecen perderse, pero siempre están ahí ... pero en un contenedor [antiguo] diferente. Por lo tanto, tome buena nota de la diferencia en docker start& docker runcomando y nunca se confunda en ellos.

Dahibato de Kiran
fuente
1

El problema similar (y de ninguna manera Dockerfile solo podría solucionarlo) me trajo a esta página.

etapa 0: para todos, esperando que Dockerfile pueda solucionarlo: hasta que --dns y --dns-search aparezcan en el soporte de Dockerfile, no hay forma de integrar recursos basados ​​en intranet.

Etapa 1: después de compilar la imagen usando Dockerfile (por cierto, es un error grave Dockerfile debe estar en la carpeta actual ), tener una imagen para implementar lo que se basa en la intranet, ejecutando Docker Run Script. ejemplo: 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"

Etapa 2: aplicar el script de ejecución de Docker en modo daemon, proporcionando registros DNS locales para tener la capacidad de descargar e implementar material local.

punto importante: el script de ejecución debe terminar con algo como /usr/bin/sudo -u ${USERNAME} bash --norcmantener el contenedor ejecutándose incluso después de que finalicen los scripts de instalación.

no , no es posible ejecutar el contenedor en modo interactivo para la automatización completa, ya que permanecerá dentro del símbolo del sistema interno hasta que se presione CTRL-p CTRL-q .

no , si el bash interactivo no se ejecutará al final del script de instalación, el contenedor terminará inmediatamente después de que finalice la ejecución del script, perdiendo todos los resultados de la instalación.

Etapa 3: el contenedor todavía se está ejecutando en segundo plano, pero no está claro si el contenedor ha finalizado el procedimiento de instalación o no todavía. usando el siguiente bloque para determinar que finaliza el procedimiento de ejecución: while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done el script continuará más adelante solo después de completar la instalación. y este es el momento adecuado para llamar: commit , proporcionando la identificación del contenedor actual, así como el nombre de la imagen de destino (puede ser el mismo que en el procedimiento de compilación / ejecución pero adjuntado con la etiqueta de instalación local. ejemplo:. docker commit containerID pack/bsp:toolchainedvea este enlace en Cómo obtener el ID de contenedor adecuado

Etapa 4: el contenedor se ha actualizado con las instalaciones locales, así como se ha confirmado en la imagen recién asignada (la que tiene la etiqueta de propósitos añadida). ahora es seguro detener el funcionamiento del contenedor. ejemplo:docker stop packbsp-cont

etapa5: en cualquier momento que el contenedor con instalaciones locales requiera ejecutarse, comience con la imagen previamente guardada. ejemplo:docker run -d -t pack/bsp:toolchained

Oleg Kokorin
fuente
1

una respuesta brillante aquí Cómo continuar una ventana acoplada que sale del usuario 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

Esa segunda línea es crucial. Entonces exec se usa en lugar de ejecutar, y no en una imagen sino en un contenedor. Y lo haces después de que se ha iniciado el contenedor.

barlop
fuente
0

Ninguna de las respuestas aborda el punto de esta elección de diseño. Creo que Docker funciona de esta manera para evitar estos 2 errores:

  • Reinicio repetido
  • Error parcial
Minh Nghĩa
fuente