¿Cómo implemento un contenedor de Docker y un contenedor de datos asociado, incluido el contenido?

Comenzaré admitiendo que soy bastante nuevo en Docker y que puedo estar abordando este problema desde el conjunto incorrecto de suposiciones... avísame si ese es el caso. He visto muchas discusiones sobre cómo Docker es útil para la implementación, pero no hay ejemplos de cómo se hace realmente.

Esta es la forma en que pensamiento funcionaría:

  1. cree el contenedor de datos para contener algunos datos persistentes en la máquina A
  2. cree el contenedor de aplicaciones que utiliza volúmenes del contenedor de datos
  3. realice algún trabajo, posiblemente cambiando los datos en el contenedor de datos
  4. detener el contenedor de aplicaciones
  5. confirmar y etiquetar el contenedor de datos
  6. enviar el contenedor de datos a un repositorio (privado)
  7. extraiga y ejecute la imagen del paso 6 en la máquina B
  8. recoger donde lo dejó en la máquina B

El paso clave aquí es el paso 5, que pensé que guardaría el estado actual (incluido el contenido del sistema de archivos). Luego, puede enviar ese estado a un repositorio y extraerlo de otro lugar, lo que le brinda un nuevo contenedor que es esencialmente idéntico al original.

Pero no parece funcionar de esa manera. Lo que encuentro es que el paso 5 no hace lo que creo que hace o el paso 7 (extraer y ejecutar la imagen) "restablece" el contenedor a su estado inicial.

He reunido un conjunto de tres imágenes y contenedores de Docker para probar esto: un contenedor de datos, un escritor que escribe una cadena aleatoria en un archivo en el contenedor de datos cada 30 segundos y un lector que simplemente echoingresa el valor en el archivo contenedor de datos y sale.

Contenedor de datos

Creado con

docker run \    --name datatest_data \    -v /datafolder \    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty# make the data folder#RUN mkdir /datafolder# write something to the data file#RUN echo "no data here!" > /datafolder/data.txt# expose the data folder#VOLUME /datafolder

Escritor

Creado con

docker run \    --rm \    --name datatest_write \    --volumes-from datatest_data \    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty# Add script#ADD run.sh /usr/local/sbin/run.shRUN chmod 755 /usr/local/sbin/*.shCMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bashwhile :do    sleep 30s    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)    echo "$NEW_STRING" >> /datafolder/data.txt    date >> /datafolder/data.txt    echo "wrote '$NEW_STRING' to file"done

Este script escribe una cadena aleatoria y la fecha / hora para /datafolder/data.txt en el contenedor de datos.

Lector

Creado con

docker run \    --rm \    --name datatest_read \    --volumes-from datatest_data \    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty# Add scriptsADD run.sh /run.shRUN chmod 0777 /run.shCMD ["/run.sh"]

run.sh:

#!/bin/bashecho "reading..."echo "-----"cat /datafolder/data.txtecho "-----"

Cuando construyo y ejecuto estos contenedores, funcionan bien y funcionan de la manera que espero:

Detener y amp; Iniciar en la máquina de desarrollo:

  1. crear el contenedor de datos
  2. ejecutar el escritor
  3. ejecute el lector de inmediato, vea el mensaje "no hay datos aquí!" mensaje
  4. espera un momento
  5. ejecute el lector, vea la cadena aleatoria
  6. detener al escritor
  7. reinicie el escritor
  8. ejecute el lector, vea la misma cadena aleatoria

Pero comprometerse y empujar no hacen lo que espero:

  1. crear el contenedor de datos
  2. ejecutar el escritor
  3. ejecute el lector de inmediato, vea el mensaje "no hay datos aquí!" mensaje
  4. espera un momento
  5. ejecute el lector, vea la cadena aleatoria
  6. detener al escritor
  7. confirmar y etiquetar el contenedor de datos con docker commit datatest_data myrepository:5000/datatest-data:latest
  8. push al repositorio
  9. eliminar todos los contenedores y volver a crearlos

En este punto, esperaría ejecutar el lector y ver la misma cadena aleatoria, ya que el contenedor de datos se ha confirmado, se ha enviado al repositorio y luego se ha recreado a partir de la misma imagen en el repositorio. Sin embargo, lo que realmente veo es el "no hay datos aquí!" mensaje.

¿Alguien puede explicar en qué me equivoco aquí? O, alternativamente, indíqueme un ejemplo de cómo se realiza la implementación con Docker.

Tienes una suposición errónea sobre cómo funcionan los volúmenes en docker. Intentaré explicar cómo los volúmenes se relacionan con los contenedores docker y las imágenes docker y, con suerte, las diferencias entre volúmenes de datos y contenedores de volumen de datos se aclarará.

Primero recordemos algunas definiciones

Imágenes de Docker

Las imágenes de Docker son esencialmente un sistema de archivos de unión + metadatos. Puede inspeccionar el contenido del sistema de archivos de unión de imágenes de docker con el docker export comando, y puede inspeccionar los metadatos de una imagen de Docker con el docker inspect comando.

Volúmenes de datos

desde el Guía del usuario de Docker:

Un volumen de datos es un directorio especialmente designado dentro de uno o más contenedores que omite el Sistema de archivos de Unión para proporcionar varias características útiles para datos persistentes o compartidos.

Es importante tener en cuenta aquí que un volumen determinado (como el directorio o el archivo que contiene datos) es reutilizable solo si existe al menos un contenedor de Docker que lo usa. Las imágenes de Docker no tienen volúmenes, solo tienen metadatos que eventualmente indican dónde se montarían los volúmenes en el sistema de archivos de la unión. Los volúmenes de datos no forman parte de los contenedores docker ni del sistema de archivos, así que, ¿dónde están? bajo /var/lib/docker/volumes en el host de docker (mientras que los contenedores se almacenan en /var/lib/docker/containers).

Contenedores de volumen de datos

Ese tipo especial de contenedor no tiene nada de especial. Son solo contenedores detenidos que utilizan un volumen de datos con el único y exclusivo objetivo de tener al menos un contenedor que utilice ese volumen de datos. Recuerde, tan pronto como se elimine el último contenedor (en ejecución o detenido) que utiliza un volumen de datos determinado, ese volumen se volverá inalcanzable a través del ejecución de docker --volumes-from opcion.

Trabajar con contenedores de volumen de datos

Cómo crear un contenedor de volumen de datos

La imagen utilizada para crear un contenedor de volumen de datos no tiene importancia, ya que dicho contenedor puede permanecer detenido y aún cumplir su propósito. Entonces, para crear un contenedor de datos llamado datatest_data para un volumen en /datafolder solo necesitas correr:

docker run --name datatest_data --volume /datafolder busybox true

Aqui base es el nombre de la imagen (convenientemente pequeño) y true es un comando que proporcionamos solo para evitar que el demonio de la ventana acoplable se queje de un comando faltante. De todos modos, después de tener un contenedor detenido llamado datatest_data con el único propósito de permitirle alcanzar ese volumen con el --volumes-from opción de la docker run comando.

Cómo leer desde un contenedor de volumen de datos

Conozco dos formas de leer un volumen de datos: la primera es a través de un contenedor. Si no puede tener un shell en un contenedor existente para acceder a ese volumen de datos, puede ejecutar un contenedor nuevo con el --volumes-from opción con el único propósito de leer esos datos.

Por ejemplo:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

La otra forma es copiar el volumen de la /var/lib/docker/volumes carpeta. Puede descubrir el nombre del volumen en esa carpeta inspeccionando los metadatos de uno de los contenedores que utilizan el volumen. Ver esta respuesta para más detalles.

Trabajar con volúmenes (desde Docker 1.9.0)

Cómo crear un volumen (desde Docker 1.9.0)

Docker 1.9.0 introdujo un nuevo comando docker volume que permite crear volúmenes :

docker volume create --name hello

Cómo leer desde un volumen (desde Docker 1.9.0)

Supongamos que ha creado un volumen llamado hello con docker volume create --name hello, puede montarlo en un contenedor con el -v opcion :

docker run -v hello:/data busybox ls /data

Acerca de enviar y empujar contenedores

Ahora debe quedar claro que, dado que los volúmenes de datos no forman parte de un contenedor (el sistema de archivos de unión), la confirmación de un contenedor para producir una nueva imagen de docker no conservará ningún dato que esté en un volumen de datos.

Realización de copias de seguridad de volúmenes de datos

La guía del usuario de Docker tiene un buen artículo sobre realización de copias de seguridad de volúmenes de datos.


Buen artículo para guardar volúmenes: http://container42.com/2014/11/03/docker-indepth-volumes/

También puede usar un contenedor de datos de Docker para implementar código

No se si es una buena práctica, pero lo hago así :

FROM ubuntu:trusty# make the data folder#RUN mkdir /data-image# in my case, I have a # ADD dest.tar /data-image/## but to follow your example :# write something to the data fileRUN echo "no data here!" > /data-image/data.txt# expose the data folder #VOLUME /datafolderENTRYPOINT cp -r /data-image/* /datafolder/

Ahora puede insertar su imagen y usar volumes-from, etc...