Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial, aprenderá a conservar los datos en una aplicación contenedora. Al ejecutarlo o actualizarlo, los datos siguen estando disponibles. Hay dos tipos principales de volúmenes que se usan para conservar los datos. Este tutorial se centra en los volúmenes con nombre.
También obtendrá información sobre los montajes de enlace, que controlan el punto de montaje exacto en el host. Puede usar montajes de enlace para conservar datos, pero también para agregar más datos a los contenedores. Cuando se trabaja en una aplicación, se puede usar un montaje de enlace para montar el código fuente en el contenedor y ver los cambios de código, responder y poder ver los cambios inmediatamente.
En este tutorial también se presentan las capas de imagen, el almacenamiento en caché de capas y las compilaciones de varias fases.
En este tutorial, aprenderá a:
- Comprender los datos entre contenedores.
- Conservar datos mediante volúmenes con nombre
- Usar montajes de enlace.
- Ver capa de imagen.
- Copiar en caché las dependencias.
- Comprender las compilaciones de varias fases.
Prerrequisitos
Este tutorial continúa con el tutorial anterior, Creación y uso compartido de una aplicación de contenedor con Visual Studio Code. Comience con ese, que incluye los requisitos previos.
Información sobre los datos entre contenedores
En esta sección, iniciará dos contenedores y creará un archivo en cada uno. Los archivos creados en un contenedor no están disponibles en otro.
Inicie un contenedor de
ubuntu
mediante este comando:docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
Este comando inicia invoca dos comandos mediante el uso de
&&
. La primera parte elige un único número aleatorio y lo escribe en/data.txt
. El segundo comando está monitoreando un archivo para mantener el contenedor en ejecución.En VS Code, en el Explorador de contenedores, haga clic con el botón derecho en el contenedor ubuntu y seleccione Asociar shell.
Se abre un terminal que ejecuta un shell en el contenedor de Ubuntu.
Ejecute el siguiente comando para ver el contenido del archivo
/data.txt
.cat /data.txt
El terminal muestra un número entre 1 y 10000.
Para usar la línea de comandos para ver este resultado, obtenga el identificador de contenedor mediante el comando
docker ps
y ejecute el siguiente comando.docker exec <container-id> cat /data.txt
Inicie otro contenedor
ubuntu
.docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
Use este comando para examinar el contenido de la carpeta.
docker run -it ubuntu ls /
No debería haber ningún archivo
data.txt
, ya que se ha escrito en el espacio de desecho solo para el primer contenedor.Seleccione estos dos contenedores de Ubuntu. Haga clic con el botón derecho y seleccione Quitar. En la línea de comandos, puede quitarlos mediante el comando
docker rm -f
.
Conservación de los datos de tareas pendientes mediante volúmenes con nombre
De forma predeterminada, la aplicación de tareas pendientes almacena sus datos en una base de datos de SQLite en /etc/todos/todo.db
.
SQLite Database es una base de datos relacional que almacena los datos en un único archivo.
Este enfoque funciona para proyectos pequeños.
Puede conservar el archivo en el host. Cuando lo pones a disposición del siguiente contenedor, la aplicación puede continuar desde donde se quedó. Si crea un volumen y lo adjunta a la carpeta (es decir, lo monta) en la que se almacenan los datos, puede conservar los datos. El contenedor escribe en el archivo todo.db y los datos se conservan en el host del volumen.
En esta sección, use un volumen con nombre. Docker mantiene la ubicación física del volumen en el disco. Consulte el nombre del volumen y Docker proporciona los datos adecuados.
Cree un volumen mediante el comando
docker volume create
.docker volume create todo-db
En CONTENEDORES, seleccione getting-started y haga clic con el botón derecho. Seleccione Detener para detener el contenedor de aplicaciones.
Para detener el contenedor desde la línea de comandos, use el comando
docker stop
.Inicie el contenedor getting-started mediante el comando siguiente.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
El parámetro de volumen especifica el volumen que se montará y la ubicación (
/etc/todos
).Actualice el explorador para volver a cargar la aplicación. Si ha cerrado la ventana del explorador, vaya a
http://localhost:3000/
. Agregue algunos elementos a la lista de tareas pendientes.Quite el contenedor getting-started para la aplicación de tareas pendientes. Haga clic con el botón derecho en el contenedor en el Explorador de contenedores y seleccione Quitar o use los
docker stop
comandos ydocker rm
.Inicie un nuevo contenedor con el mismo comando:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Este comando monta la misma unidad que antes. Actualice el explorador. Los elementos que agregó siguen estando en la lista.
Quite de nuevo el contenedor getting-started.
Los volúmenes con nombre y los montajes de enlace, que se tratan a continuación, son los tipos principales de volúmenes que admite una instalación predeterminada del motor de Docker.
Propiedad | Volúmenes con nombre | Montajes de enlace |
---|---|---|
Ubicación del host | Elección de Docker | Usted controla |
Ejemplo de montaje (mediante -v ) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
Rellena el nuevo volumen con el contenido del contenedor. | Sí | No |
Admite controladores de volumen | Sí | No |
Hay muchos complementos de controlador de volumen disponibles para admitir NFS, SFTP, NetApp, etc. Estos complementos son especialmente importantes para ejecutar contenedores en varios hosts en un entorno agrupado, como Swarm o Kubernetes.
Si se pregunta dónde almacena realmente Docker los datos, ejecute el comando siguiente.
docker volume inspect todo-db
Observe la salida, que será similar a este resultado.
[
{
"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 donde se almacenan los datos.
En la mayoría de los equipos, necesita acceso raíz para acceder a este directorio desde el host.
Uso de montajes de enlace
Con los montajes de enlace, puede controlar el punto de montaje exacto en el host. Este enfoque conserva los datos, pero a menudo se usa para proporcionar más datos en contenedores. Puede usar un montaje de enlace para montar el código fuente en el contenedor y ver los cambios en el código, reaccionar y consultar los cambios de inmediato.
Para ejecutar el contenedor a fin de admitir un flujo de trabajo de desarrollo, siga estos pasos:
Quite los contenedores
getting-started
.En la carpeta
app
, ejecute el siguiente comando.docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:lts-alpine sh -c "yarn install && yarn run dev"
Este comando contiene los parámetros siguientes.
-
-dp 3000:3000
igual que antes. Ejecute en modo desasociado y cree una asignación de puertos. -
-w /app
: directorio de trabajo dentro del contenedor. -
-v ${PWD}:/app"
: montaje de enlace del directorio actual desde el host del contenedor en el directorio/app
. -
node:lts-alpine
La imagen que se va a usar. Se trata de la imagen base para la aplicación del Dockerfile. -
sh -c "yarn install && yarn run dev"
Un comando. Inicia un shell mediantesh
y ejecutayarn install
para instalar todas las dependencias. Después, ejecutayarn run dev
. Si consulta el archivopackage.json
, el scriptdev
inicianodemon
.
-
Puede ver los registros mediante
docker logs
.docker logs -f <container-id>
$ nodemon src/index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000
Cuando vea la entrada final de esta lista, la aplicación se está ejecutando.
Cuando haya terminado de ver los registros, seleccione cualquier tecla en la ventana del terminal o seleccione Ctrl+C en una ventana externa.
En VS Code, abre src/static/js/app.js. Cambie el texto del botón Agregar elemento de la línea 109.
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
Guarde sus cambios.
Actualice el explorador. Deberás ver el cambio.
Quite el
node:lts-alpine
contenedor.En la
app
carpeta , ejecute el siguiente comando para quitar lanode_modules
carpeta creada en los pasos anteriores.rm -r node_modules
Ver capas de imagen
Puede ver las capas que componen una imagen.
Ejecute el comando docker image history
para ver el comando que se usó para crear cada capa dentro de una imagen.
Usa
docker image history
para ver las capas en la imagen de introducción que creaste anteriormente en el tutorial.docker image history getting-started
El resultado debe ser similar a este resultado.
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
Cada una de las líneas representa una capa de la imagen. La salida muestra la base en la parte inferior con la capa más reciente en la parte superior. Con esta información, puede ver el tamaño de cada capa, lo que ayuda a diagnosticar imágenes grandes.
Varias de las líneas están truncadas. Si agrega el parámetro
--no-trunc
, obtendrá la salida completa.docker image history --no-trunc getting-started
Dependencias de caché
Una vez que cambia una capa, también se deben volver a crear todas las capas de bajada. Aquí puede ver de nuevo el Dockerfile:
FROM node:lts-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]
Cada comando del Dockerfile se convierte en una nueva capa de la imagen.
Para minimizar el número de capas, puede reestructurar su Dockerfile para permitir la caché de dependencias.
En el caso de las aplicaciones basadas en nodos, esas dependencias se definen en el archivo package.json
.
El enfoque consiste en copiar solo ese archivo en primer lugar, instalar las dependencias y, a continuación, copiar todo lo demás.
El proceso solo vuelve a crear las dependencias de Yarn si se ha producido un cambio en package.json
.
Actualice el Dockerfile para copiar primero
package.json
, instale las dependencias y, después, copie todo lo demás. Este es el nuevo archivo:FROM node:lts-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "/app/src/index.js"]
Cree una nueva imagen mediante
docker build
.docker build -t getting-started .
Debería ver resultados similares a los siguientes resultados:
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:lts-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Running in d53a06c9e4c2 yarn install v1.17.3 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.9: The platform "linux" is incompatible with this module. info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 10.89s. Removing intermediate container d53a06c9e4c2 ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> a239a11f68d8 Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 49999f68df8f Removing intermediate container 49999f68df8f ---> e709c03bc597 Successfully built e709c03bc597 Successfully tagged getting-started:latest
Se reconstruyeron todas las capas. Este resultado es esperado porque cambiaste el Dockerfile.
Realice un cambio en el src/static/index.html. Por ejemplo, cambie el título para decir "The Awesome Todo App".
Compile la imagen de Docker ahora con
docker build
de nuevo. Esta vez, la salida debería tener un aspecto un poco diferente.Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:lts-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> Using cache ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Using cache ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> cccde25a3d9a Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 2be75662c150 Removing intermediate container 2be75662c150 ---> 458e5c6f080c Successfully built 458e5c6f080c Successfully tagged getting-started:latest
Dado que usa la memoria caché de compilación, debe ir mucho más rápido.
Compilaciones de varias fases
Las compilaciones de varias fases son una herramienta increíblemente eficaz que permite usar varias fases para crear una imagen. Existen varias ventajas para ellos:
- Separar las dependencias en tiempo de compilación de las dependencias en tiempo de ejecución
- Reducir el tamaño general de la imagen mediante el envío solo de lo que la aplicación necesita ejecutar
En esta sección se proporcionan ejemplos breves.
Ejemplo de Maven/Tomcat
Al compilar aplicaciones basadas en Java, se necesita un JDK para compilar el código fuente en código de bytes de Java. Ese JDK no es necesario en producción. Es posible que esté usando herramientas como Maven o Gradle para ayudar a compilar la aplicación. Esas herramientas tampoco son necesarias en la imagen final.
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
En este ejemplo se usa una fase, build
, para realizar la compilación de Java real mediante Maven.
La segunda fase (a partir de "FROM tomcat") copia los archivos de la fase build
.
La imagen final es solo la última fase que se crea, que se puede invalidar mediante el parámetro --target
.
Ejemplo de React
Al compilar aplicaciones de React, necesita un entorno de Node para compilar el código JavaScript, hojas de estilos de Sass y mucho más en HTML estático, JavaScript y CSS. Si no va a realizar la representación del lado servidor, ni siquiera necesita un entorno de Node para la compilación de producción.
FROM node:lts-alpine AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
En este ejemplo se usa una imagen de node:lts-alpine
para realizar la compilación, que maximiza el almacenamiento en caché de capas y, a continuación, copia la salida en un contenedor de nginx.
Limpieza de recursos
Mantén todo lo que has hecho hasta ahora para continuar la serie de tutoriales.
Pasos siguientes
Ha aprendido sobre las opciones para conservar los datos de las aplicaciones de contenedor.
¿Qué quieres hacer a continuación?
Trabajar con varios contenedores mediante Docker Compose:
Creación de aplicaciones de varios contenedores con MySQL y Docker Compose
Implementación en Azure Container Apps:
Implementación en Azure App Service