¿Cómo implemento un contenedor acoplable y un contenedor de datos asociado, incluidos los contenidos?

18

Comenzaré admitiendo que soy bastante nuevo en Docker y que podría estar abordando este problema desde un conjunto equivocado de suposiciones ... avíseme si ese es el caso. He visto mucha discusión 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 pensé que funcionaría:

  1. cree el contenedor de datos para contener algunos datos persistentes en la máquina A
  2. crear el contenedor de la aplicación que usa volúmenes del contenedor de datos
  3. hacer algo de trabajo, potencialmente cambiando los datos en el contenedor de datos
  4. detener el contenedor de la aplicación
  5. confirmar y etiquetar el contenedor de datos
  6. empujar el contenedor de datos a un repositorio (privado)
  7. tire y ejecute la imagen del paso 6 en la máquina B
  8. retomar donde lo dejó en la máquina B

El paso clave aquí es el paso 5, que pensé que salvaría el estado actual (incluidos los contenidos del sistema de archivos). Luego, podría llevar ese estado a un repositorio y extraerlo de otro lugar, lo que le dará 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 (al tirar 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 s, y un lector que simplemente echoes el valor en los datos archivo contenedor y salidas.

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.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
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 /datafolder/data.txten 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 scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

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

Stop & Start en la máquina de desarrollo:

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

Pero comprometerse y empujar no hacen lo que espero:

  1. crear el contenedor de datos
  2. corre el escritor
  3. ejecute el lector de inmediato, vea el mensaje "¡no hay datos aquí!" mensaje
  4. espera un momento
  5. ejecuta el lector, mira 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. empujar al repositorio
  9. eliminar todos los contenedores y recrearlos

En este punto, esperaría ejecutar el lector y ver la misma cadena aleatoria, ya que el contenedor de datos se ha confirmado, enviado al repositorio y luego 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 dónde me estoy equivocando aquí? ¿O, alternativamente, señalarme un ejemplo de cómo se realiza la implementación con Docker?

Kryten
fuente

Respuestas:

22

Tienes una suposición errónea sobre cómo funcionan los volúmenes en Docker. Trataré de explicar cómo los volúmenes se relacionan con los contenedores acoplables y las imágenes de acopladores y espero que las diferencias entre los volúmenes de datos y los contenedores de volúmenes de datos se aclaren.

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 exportcomando, y puede inspeccionar los metadatos de una imagen de Docker con el docker inspectcomando.

Volúmenes de datos

de la 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 la 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 archivo que contiene datos) es reutilizable solo si existe al menos un contenedor acoplable que lo use. 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 tampoco forman parte del sistema de archivos de unión de contenedores acoplables, entonces, ¿dónde están? under /var/lib/docker/volumesen el host 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 especial. Solo son contenedores detenidos que usan un volumen de datos con el único y único objetivo de tener al menos un contenedor que use ese volumen de datos. Recuerde, tan pronto como se elimine el último contenedor (en ejecución o detenido) que utiliza un volumen de datos dado, ese volumen no será accesible a través de la opción de ejecución de Docker --volumes-from .

Trabajando 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 seguir cumpliendo su propósito. Entonces, para crear un contenedor de datos con el nombre datatest_datade un volumen /datafolder, solo necesita ejecutar:

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

Aquí baseestá el nombre de la imagen (convenientemente pequeño) y truees un comando que proporcionamos solo para evitar que el Docker Daemon se queje de la falta de un comando. De todos modos, después de que haya un contenedor detenido nombrado datatest_datacon el único propósito de permitirle alcanzar ese volumen con la --volumes-fromopción del docker runcomando.

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 nuevo contenedor con la --volumes-fromopció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/volumescarpeta. Puede descubrir el nombre del volumen en esa carpeta inspeccionando los metadatos de uno de los contenedores utilizando el volumen. Vea esta respuesta para más detalles.

Trabajando 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 volumeque permite crear volúmenes:

docker volume create --name hello

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

Digamos que creó un volumen hellocon nombre docker volume create --name hello, puede montarlo en un contenedor con la -vopción:

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

Acerca de comprometer y empujar contenedores

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

Hacer copias de seguridad de volúmenes de datos

La guía del usuario de Docker tiene un buen artículo sobre cómo hacer copias de seguridad de los volúmenes de datos .


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

Thomasleveil
fuente
Parece que "La imagen utilizada para crear un contenedor de volumen de datos no tiene importancia" no es del todo correcta. Simplemente intente con una imagen "scratch" que le dará "exec:" true ": archivo ejecutable no encontrado"
tcurdt
A pesar de este error, su contenedor se creará y cumplirá su función de titular de volumen
Thomasleveil
1
Hm, quizás valga la pena abrir un problema para eso entonces.
tcurdt
no, se espera ese comportamiento ya que la imagen scratch es una imagen vacía que no puede tener el /bin/truebinario (o cualquier otro) de todos modos
Thomasleveil
1
Sólo una cosa. Usted dijo que "tan pronto como se elimine el último contenedor (en ejecución o detenido) que utiliza un volumen de datos dado, Docker destruirá ese volumen de datos de / var / lib / docker / volume", pero eso no es realmente cierto: solo vea: docs.docker.com/userguide/dockervolumes (los volúmenes de datos persisten incluso si se elimina el contenedor en sí. Debe especificar el docker rm -vcomando en el último contenedor para eliminar también un volumen)
juanra
1

También podría usar un contenedor de datos de Docker para implementar código

No sé 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 file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

Ahora puede empujar su imagen y usar volúmenes de, etc.

jmny
fuente
Esto es lo que estoy buscando, pero la respuesta aceptada menciona explícitamente que esto no se puede hacer. Voy a probarlo ahora.
andho
1
En una segunda mirada, la respuesta aceptada dice que los volúmenes (o datos dentro de él) no se confirmarán, pero puede agregar los datos al contenedor usando COPYo ADDy crear el volumen usando VOLUMEel Dockerfile.
andho