Compartir comentarios
Las respuestas se generan en base a la documentación.

Persistir la base de datos

Por si no lo habías notado, tu lista de tareas está vacía cada vez que inicias el contenedor. ¿Por qué ocurre esto? En esta parte, profundizarás en el funcionamiento de los contenedores.

El sistema de archivos del contenedor

Cuando un contenedor se ejecuta, utiliza las diversas capas de una imagen para su sistema de archivos. Cada contenedor también obtiene su propio "espacio de borrador" (scratch space) para crear, actualizar y eliminar archivos. Los cambios realizados no se verán en otros contenedores, incluso si están utilizando la misma imagen.

Ver esto en la práctica

Para ver esto en acción, vas a iniciar dos contenedores. En un contenedor, crearás un archivo. En el otro contenedor, verificarás si ese mismo archivo existe.

  1. Inicia un contenedor de Alpine y crea un archivo nuevo en él.

    $ docker run --rm alpine touch greeting.txt
    
    Tip

    Cualquier comando que especifiques después del nombre de la imagen (en este caso, alpine) se ejecuta dentro del contenedor. En este caso, el comando touch greeting.txt coloca un archivo llamado greeting.txt en el sistema de archivos del contenedor.

  2. Ejecuta un nuevo contenedor de Alpine y utiliza el comando stat para verificar si el archivo existe.

    $ docker run --rm alpine stat greeting.txt
    

    Deberías ver una salida similar a la siguiente que indica que el archivo no existe en el nuevo contenedor.

    stat: can't stat 'greeting.txt': No such file or directory
    

El archivo greeting.txt creado por el primer contenedor no existía en el segundo contenedor. Esto se debe a que la "capa superior" de escritura de cada contenedor está aislada. Aunque ambos contenedores comparten las mismas capas subyacentes que componen la imagen base, la capa de escritura es única para cada contenedor.

Volúmenes de contenedor

Con el experimento anterior, viste que cada contenedor comienza desde la definición de la imagen cada vez que se inicia. Si bien los contenedores pueden crear, actualizar y eliminar archivos, esos cambios se pierden al eliminar el contenedor, ya que Docker aísla todos los cambios dentro de ese contenedor. Con los volúmenes, puedes cambiar todo esto.

Los volúmenes proporcionan la capacidad de conectar rutas específicas del sistema de archivos del contenedor de vuelta a la máquina host. Si montas un directorio en el contenedor, los cambios en ese directorio también se verán en la máquina host. Si montas ese mismo directorio a lo largo de los reinicios del contenedor, verás los mismos archivos.

Existen dos tipos principales de volúmenes. Con el tiempo utilizarás ambos, pero comenzarás con los montajes de volumen (volume mounts).

Persistir los datos de las tareas

De forma predeterminada, la aplicación de tareas almacena sus datos en una base de datos SQLite en /etc/todos/todo.db en el sistema de archivos del contenedor. Si no estás familiarizado con SQLite, ¡no te preocupes! Es simplemente una base de datos relacional que almacena todos los datos en un solo archivo. Aunque esto no es lo mejor para aplicaciones a gran escala, funciona para pequeñas demostraciones. Más adelante aprenderás a cambiar esto a un motor de base de datos diferente.

Dado que la base de datos es un único archivo, si puedes persistir ese archivo en el host y ponerlo a disposición del siguiente contenedor, este debería poder continuar donde lo dejó el anterior. Al crear un volumen y conectarlo (a menudo llamado "montar") al directorio donde almacenaste los datos, puedes persistirlos. A medida que tu contenedor escribe en el archivo todo.db, persistirá los datos en el host dentro del volumen.

Como se mencionó, vas a utilizar un montaje de volumen. Piensa en un montaje de volumen como un cubo de datos opaco. Docker gestiona completamente el volumen, incluida la ubicación de almacenamiento en el disco. Solo necesitas recordar el nombre del volumen.

Crear un volumen e iniciar el contenedor

Puedes crear el volumen e iniciar el contenedor utilizando la CLI o la interfaz gráfica de Docker Desktop.

  1. Crea un volumen utilizando el comando docker volume create.

    $ docker volume create todo-db
    
  2. Detén y elimina el contenedor de la aplicación de tareas una vez más con docker rm -f <id>, ya que todavía se está ejecutando sin utilizar el volumen persistente.

  3. Inicia el contenedor de la aplicación de tareas, pero agrega la opción --mount para especificar un montaje de volumen. Dale un nombre al volumen y móntalo en /etc/todos en el contenedor, lo que capturará todos los archivos creados en esa ruta.

    $ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
    
    Note

    Si estás utilizando Git Bash, debes usar una sintaxis diferente para este comando.

    $ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=//etc/todos getting-started
    

    Para obtener más detalles sobre las diferencias de sintaxis de Git Bash, consulta Trabajar con Git Bash.

Para crear un volumen:

  1. Selecciona Volumes en Docker Desktop.
  2. En Volumes, selecciona Create.
  3. Especifica todo-db como el nombre del volumen y luego selecciona Create.

Para detener y eliminar el contenedor de la aplicación:

  1. Selecciona Containers en Docker Desktop.
  2. Selecciona Delete (Eliminar) en la columna Actions del contenedor.

Para iniciar el contenedor de la aplicación de tareas con el volumen montado:

  1. Selecciona el cuadro de búsqueda en la parte superior de Docker Desktop.

  2. En la ventana de búsqueda, selecciona la pestaña Images.

  3. En el cuadro de búsqueda, especifica el nombre de la imagen: getting-started.

    Tip

    Utiliza el filtro de búsqueda para filtrar las imágenes y mostrar únicamente Local images (Imágenes locales).

  4. Selecciona tu imagen y luego selecciona Run.

  5. Selecciona Optional settings.

  6. En Host port, especifica el puerto, por ejemplo, 3000.

  7. En Host path, especifica el nombre del volumen, todo-db.

  8. En Container path, especifica /etc/todos.

  9. Selecciona Run.

Verificar que los datos persistan

  1. Una vez que el contenedor se inicie, abre la aplicación y agrega algunos elementos a tu lista de tareas.

    Elementos agregados a la lista de tareas
  2. Detén y elimina el contenedor de la aplicación de tareas. Utiliza Docker Desktop o docker ps para obtener el ID, y luego docker rm -f <id> para eliminarlo.

  3. Inicia un nuevo contenedor utilizando los pasos anteriores.

  4. Abre la aplicación. Deberías ver que tus elementos aún están en la lista.

  5. Continúa y elimina el contenedor cuando hayas terminado de revisar tu lista.

Ahora has aprendido a persistir datos.

Profundizar en el volumen

Mucha gente pregunta con frecuencia: "¿Dónde almacena Docker mis datos cuando utilizo un volumen?". Si deseas saberlo, puedes utilizar el comando docker volume inspect.

$ docker volume inspect todo-db

Deberías ver una salida como la siguiente:

[
    {
        "CreatedAt": "2019-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

El Mountpoint es la ubicación real de los datos en el disco. Ten en cuenta que, en la mayoría de las máquinas, necesitarás tener acceso de superusuario (root) para acceder a este directorio desde el host.

Resumen

En esta sección, aprendiste cómo persistir los datos de los contenedores.

Información relacionada:

Siguientes pasos

A continuación, aprenderás cómo puedes desarrollar tu aplicación de manera más eficiente utilizando montajes de tipo bind (bind mounts).

Usar bind mounts