Descripción de la instrucción "VOLUMEN" en DockerFile


A continuación se muestra el contenido de mi" Dockerfile "

FROM node:boron

# Create app directory
RUN mkdir -p /usr/src/app

# change working dir to /usr/src/app
WORKDIR /usr/src/app

VOLUME . /usr/src/app

RUN npm install

EXPOSE 8080

CMD ["node" , "server" ]

En este archivo estoy esperando " VOLUMEN . /usr/src /app" instrucción para montar el contenido del directorio de trabajo actual en el host que se montará en la carpeta/usr/src / app del contenedor.

Por favor, hágamelo saber si esta es la manera correcta ?

Author: refactor, 2017-01-30

2 answers

El tutorial oficial de docker dice:

Un volumen de datos es un directorio especialmente designado dentro de uno o más contenedores que omite el Sistema de archivos Union. Los volúmenes de datos proporcionan varias características útiles para datos persistentes o compartidos:

  • Los volúmenes se inicializan cuando se crea un contenedor. Si la imagen base del contenedor contiene datos en el punto de montaje especificado,
    que los datos existentes se copian en el nuevo volumen tras volumen
    inicialización. (Tenga en cuenta que esto no se aplica al montar un host
    directorio.)
  • Los volúmenes de datos se pueden compartir y reutilizar entre contenedores.

  • Los cambios en un volumen de datos se realizan directamente.

  • Los cambios en un volumen de datos no se incluirán cuando actualice una imagen.

  • Los volúmenes de datos persisten incluso si se elimina el propio contenedor.

Dentro de Dockerfile puede especificar solo el destino del volumen dentro de contenedor. por ejemplo, /usr/src/app.

Cuando ejecuta el contenedor, por ejemplo, docker run --volume=/opt:/usr/src/app my_image puede pero no es necesario especificar el punto de montaje (/opt) en la máquina host. Si no especifica el argumento volume volume, el punto de montaje se elegirá automáticamente

 14
Author: Bukharov Sergey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-30 12:15:59

En resumen: No, su VOLUME instrucción no es correcta.

VOLUME de Dockerfile especifica uno o más volúmenes dados caminos del lado del contenedor. Pero no permite que el autor de la imagen especifique una ruta de host. En el lado del host, los volúmenes se crean con un nombre similar a un ID muy largo dentro de la raíz de Docker. En mi máquina esto es /var/lib/docker/volumes.

Nota: Debido a que el nombre autogenerado es extremadamente largo y no tiene sentido desde la perspectiva humana, estos volúmenes a menudo se refieren como "sin nombre" o "anónimo".

Tu ejemplo que usa un '.'character ni siquiera se ejecutará en mi máquina, no importa si hago del punto el primer o segundo argumento. Recibo este mensaje de error:

Docker: Respuesta de error del demonio: oci runtime error: container_linux.go: 265: iniciar el proceso de contenedor causó " process_linux.go: 368: container init caused \ " open/dev / ptmx: no such file or directory\"".

Sé que lo que se ha dicho hasta este punto es probablemente no es muy valioso para alguien que intenta entender VOLUME y -v y ciertamente no proporciona una solución para lo que intenta lograr. Así que, con suerte, los siguientes ejemplos arrojarán algo más de luz sobre estas cuestiones.

Minitutorial: Especificando volúmenes

Dado este Dockerfile:

FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2

(Para el resultado de este minitutorial, no importa si especificamos vol1 vol2 o /vol1 /vol2 - no me preguntes por qué)

Construir se:

docker build -t my-openjdk

Ejecutar:

docker run --rm -it my-openjdk

Dentro del contenedor, ejecute ls y notará que existen dos directorios; /vol1 y /vol2.

Ejecutar el contenedor también crea dos directorios, o "volúmenes", en el lado del host.

Mientras se ejecuta el contenedor, ejecute docker volume ls en la máquina host y verá algo como esto (he reemplazado la parte central del nombre con dos puntos para brevedad):

DRIVER    VOLUME NAME
local     c984..e4fc
local     f670..49f0

De vuelta en el container , execute touch /vol1/weird-ass-file (crea un archivo en blanco en dicha ubicación).

Este archivo ahora está disponible en la máquina host, en uno de los volúmenes sin nombre lol. Me tomó dos intentos porque primero probé el primer volumen de la lista, pero finalmente encontré mi archivo en el segundo volumen de la lista, usando este comando en la máquina host:

sudo ls /var/lib/docker/volumes/f670..49f0/_data

Del mismo modo, puede intentar eliminar este archivo en el host y también se eliminará en el contenedor.

Nota: El _data la carpeta también se conoce como un "punto de montaje".

Salga del contenedor y enumere los volúmenes en el host. Se han ido. Usamos el indicador --rm al ejecutar el contenedor y esta opción elimina efectivamente no solo el contenedor al salir, sino también los volúmenes.

Ejecute un nuevo contenedor, pero especifique un volumen utilizando -v:

docker run --rm -it -v /vol3 my-openjdk

Este agrega un tercer volumen y todo el sistema termina teniendo tres volúmenes sin nombre. El comando habría se estrelló si solo especificamos -v vol3. El argumento debe ser un camino absoluto dentro de el contenedor. En el lado del host, el nuevo tercer volumen es anónimo y reside junto con los otros dos volúmenes en /var/lib/docker/volumes/.

Se dijo anteriormente que el Dockerfile no puede asignar a una ruta de host, lo que plantea un problema para nosotros al intentar traer archivos desde el host al contenedor durante el tiempo de ejecución. Una sintaxis -v diferente resuelve este problema.

Imagina que tengo una subcarpeta en el directorio de mi proyecto ./src que deseo sincronizar con /src dentro del contenedor. Este comando hace el truco:

docker run -it -v $(pwd)/src:/src my-openjdk

Ambos lados del carácter : esperan una ruta absoluta. El lado izquierdo es una ruta absoluta en la máquina host, el lado derecho es una ruta absoluta dentro del contenedor. pwd es un comando que "imprime el directorio actual/de trabajo". Poner el comando en $() toma el comando entre paréntesis, lo ejecuta en una subcapa y devuelve el absoluto ruta a nuestro directorio de proyectos.

Poniendo todo junto, supongamos que tenemos ./src/Hello.java en nuestra carpeta de proyecto en la máquina host con el siguiente contenido:

public class Hello {
    public static void main(String... ignored) {
        System.out.println("Hello, World!");
    }
}

Construimos este Dockerfile:

FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello

Ejecutamos este comando:

docker run -v $(pwd)/src:/src my-openjdk

Esto imprime " Hola, Mundo!".

La mejor parte es que somos completamente libres de modificar el .archivo java con un nuevo mensaje para otra salida en una segunda ejecución-sin tener que reconstruir la imagen=)

Final observaciones

Soy bastante nuevo en Docker, y el mencionado "tutorial" refleja información que recopilé de un hackathon de línea de comandos de 3 días. Estoy casi avergonzado de no haber podido proporcionar enlaces a una documentación clara similar al inglés que respalde mis declaraciones, pero honestamente creo que esto se debe a la falta de documentación y no a un esfuerzo personal. Sé que los ejemplos funcionan como se anuncian usando mi configuración actual que es "Windows 10 - > Vagrant 2.0.0 - > Docker 17.09.0-ce".

El el tutorial no resuelve el problema "cómo especificamos la ruta del contenedor en el Dockerfile y dejamos que el comando run solo especifique la ruta del host". Puede que haya una manera, pero no la he encontrado.

Finalmente, tengo la sensación de que especificar VOLUME en el Dockerfile no es solo raro, sino que probablemente sea una buena práctica no usar nunca VOLUME. Por dos razones. La primera razón que ya hemos identificado: No podemos especificar la ruta de host - que es una buena cosa porque Dockerfiles debe ser muy agnóstico a los detalles de una máquina host. Pero la segunda razón es que la gente puede olvidar usar la opción --rm al ejecutar el contenedor. Uno podría recordar quitar el recipiente pero olvidar quitar el volumen. Además, incluso con lo mejor de la memoria humana, podría ser una tarea desalentadora averiguar cuál de todos los volúmenes anónimos es seguro eliminar.

 68
Author: Martin Andersson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-05 15:23:22