Recuperación e implementación local de una imagen de Docker existente

Completado

Docker es una tecnología que permite implementar aplicaciones y servicios de forma rápida y sencilla. Una aplicación de Docker se ejecuta con una imagen de Docker. Una imagen de Docker es un entorno previamente empaquetado que contiene el código de la aplicación y el entorno en el que se ejecuta el código.

En el escenario corporativo que se ha descrito antes, quiere investigar la viabilidad de empaquetar y ejecutar una aplicación con Docker. Decide compilar e implementar una imagen de Docker en la que se ejecuta una aplicación web de prueba.

En esta unidad, obtendrá información sobre los conceptos clave y los procesos implicados en la ejecución de una aplicación en contenedores almacenada en una imagen de Docker.

Información general de Docker

Docker es una herramienta para ejecutar aplicaciones en contenedores. Una aplicación en contenedores incluye la aplicación y el sistema de archivos que compone el entorno en el que se ejecuta. Por ejemplo, una aplicación en contenedores podría constar de una base de datos y de otra información relacionada de software y configuración necesaria para ejecutar la aplicación.

Normalmente, una aplicación en contenedores tiene una superficie de memoria mucho menor que una máquina virtual configurada para ejecutar la misma aplicación. Esta superficie de memoria más reducida se debe a que una máquina virtual tiene que facilitar el sistema operativo completo y el entorno de respaldo asociado. Un contenedor de Docker no tiene esta sobrecarga, porque Docker usa el kernel del sistema operativo del equipo host para alimentar el contenedor. La descarga y el inicio de una imagen de Docker son mucho más rápidos y más eficaces en lo que al espacio respecta que la descarga y ejecución de una máquina virtual que proporciona una funcionalidad similar.

Para crear una aplicación en contenedores, se compila una imagen que contiene un conjunto de archivos y una sección de información de configuración que usa Docker. Para ejecutar la aplicación, hay que pedir a Docker que inicie un contenedor basado en la imagen. Cuando el contenedor se inicia, Docker usa la configuración de la imagen para determinar qué aplicación se va a ejecutar dentro del contenedor. Docker proporciona los recursos del sistema operativo y la seguridad necesaria. Garantiza que los contenedores se ejecutan simultáneamente y permanecen relativamente aislados.

Importante

Docker no proporciona el nivel de aislamiento disponible con las máquinas virtuales. Una máquina virtual implementa el aislamiento en el nivel de hardware. Los contenedores de Docker comparten bibliotecas y recursos del sistema operativo subyacentes. Sin embargo, Docker impide que un contenedor acceda a los recursos de otro si esos contenedores no están configurados para ello.

Puede ejecutar Docker en el equipo de escritorio o portátil si realiza el desarrollo y las pruebas de forma local. Para los sistemas de producción, Docker está disponible para entornos de servidor, incluidas muchas variantes de Linux y Microsoft Windows Server 2016. Muchos proveedores también admiten Docker en la nube. Por ejemplo, puede almacenar imágenes de Docker en Azure Container Registry y ejecutar contenedores con Azure Container Instances.

En este módulo, usará Docker localmente para compilar y ejecutar una imagen. Posteriormente, cargará la imagen en Azure Container Registry y la ejecutará en Azure Container Instances. Esta versión de Docker es adecuada para el desarrollo local y las pruebas de imágenes de Docker.

Imágenes de Docker de Windows y Linux

Docker se desarrolló en principio para Linux y se ha ampliado después para admitir Windows. Las imágenes de Docker individuales se basan en Windows o Linux, pero no en ambos al mismo tiempo. El sistema operativo de la imagen determina qué tipo de entorno del sistema operativo se usa dentro del contenedor.

Los creadores de imágenes de Docker que quieran ofrecer una funcionalidad similar tanto en las imágenes basadas en Linux como en Windows pueden crear esas imágenes por separado. Por ejemplo, Microsoft ofrece imágenes de Docker para Windows y Linux con un entorno de ASP.NET Core que se puede usar como base para las aplicaciones ASP.NET Core en contenedores.

En los equipos Linux con Docker instalado solo se pueden ejecutar contenedores de Linux. En los equipos Windows con Docker instalado se pueden ejecutar los dos tipos de contenedores. Para ello, Windows usa una máquina virtual para ejecutar un sistema Linux y usa el sistema virtual de Linux para ejecutar los contenedores de Linux.

En este módulo, compilará y ejecutará una imagen basada en Linux.

Registros de Docker y Docker Hub

Las imágenes de Docker se almacenan y se ofrecen en registros. Un registro es un servicio web al que Docker se puede conectar para cargar y descargar imágenes de contenedor. El registro más conocido es Docker Hub, que es un registro público. Muchos usuarios y organizaciones publican imágenes en Docker Hub, y puede descargarlas y ejecutarlas con Docker si lo ejecuta en el escritorio, en un servidor o en la nube. Puede crear una cuenta de Docker Hub y cargar imágenes de forma gratuita.

Un registro se organiza como una serie de repositorios. Cada repositorio contiene varias imágenes de Docker que comparten un nombre común (y, por lo general, la misma finalidad y funcionalidad). Estas imágenes suelen tener versiones diferentes que se identifican con una etiqueta. Este mecanismo permite publicar y mantener varias versiones de imágenes por motivos de compatibilidad. Cuando descargue y ejecute una imagen, tendrá que especificar el registro, el repositorio y la etiqueta de versión de la imagen. Las etiquetas son etiquetas de texto, y puede usar su sistema de numeración (v1.0, v1.1, v1.2, v2.0, etc.).

Imagine que quiere usar la imagen de Docker de ASP.NET Core Runtime. Esta imagen está disponible en dos versiones:

  • mcr.microsoft.com/dotnet/core/aspnet:2.2
  • mcr.microsoft.com/dotnet/core/aspnet:2.1

Ahora, imagine que quiere usar las imágenes de Docker de ejemplo de .NET Core. Aquí tenemos cuatro versiones disponibles entre las que elegir:

  • mcr.microsoft.com/dotnet/samples:dotnetapp
  • mcr.microsoft.com/dotnet/samples:aspnetapp

Nota:

Una sola imagen puede tener varias etiquetas asignadas. Por convención, a la versión más reciente de una imagen se le asigna la etiqueta latest, además de otra que describe su número de versión. Cuando publique una nueva versión de una imagen, puede volver a asignar la etiqueta latest para hacer referencia a la nueva imagen.

Un repositorio también es la unidad de privacidad de una imagen. Si no quiere compartir una imagen, puede convertir en privado el repositorio. Puede conceder acceso a otros usuarios con los que quiera compartir la imagen.

Búsquedas en Docker Hub y extracción de una imagen

Nota:

No es necesario completar ninguno de los ejemplos ni ejecutar ninguno de los códigos de las secciones siguientes. Lo hará en la unidad siguiente.

A menudo encontrará que en Docker Hub hay una imagen que coincide con el tipo de aplicación que quiere incluir en contenedores. Puede descargar esa imagen y ampliarla con código de la aplicación.

Docker Hub contiene varios miles de imágenes. Puede buscar y examinar un registro mediante Docker desde la línea de comandos o desde el sitio web de Docker Hub. El sitio web permite buscar, filtrar y seleccionar imágenes por tipo y por publicador. En la imagen siguiente se muestra un ejemplo de la página de búsqueda.

Captura de pantalla de la página de búsqueda de Docker Hub en la que se enumeran varias imágenes de contenedor.

Para recuperar una imagen, se usa el comando docker pull con el nombre de la imagen. Docker descargará de forma predeterminada la imagen etiquetada con latest desde ese repositorio en Docker Hub si solo se especifica el nombre del repositorio. Cabe decir que el comando se puede modificar para obtener diferentes etiquetas y desde distintos repositorios. En este ejemplo se captura la imagen con la etiqueta aspnetapp del repositorio mcr.microsoft.com/dotnet/core/samples:aspnetapp. Esta imagen contiene una aplicación web de ASP.NET Core sencilla.

Nota:

Los ejemplos de esta unidad están diseñados para mostrar la sintaxis de los distintos comandos de Docker. No es necesario que los ejecute mientras lee esta unidad. En los ejercicios que siguen a esta unidad se le guiará por la forma de trabajar directamente con Docker.

docker pull mcr.microsoft.com/dotnet/samples:aspnetapp

Al capturar una imagen, Docker la almacena de forma local y la pone a disposición de los contenedores en ejecución. Puede ver las imágenes en el registro local con el comando docker image list.

docker image list

La salida se parece al ejemplo siguiente:

REPOSITORY TAG IMAGE ID CREATED SIZE
mcr.microsoft.com/dotnet/samples   aspnetapp           6e2737d83726        6 days ago          263MB

Puede usar el identificador de nombre de imagen para hacer referencia a la imagen en otros muchos comandos de Docker.

Ejecución de un contenedor de Docker

Use el comando docker run para iniciar un contenedor. Especifique la imagen que se va a ejecutar con su nombre o identificador. Si todavía no ha aplicado docker pull a la imagen, Docker lo hará de forma automática.

docker run mcr.microsoft.com/dotnet/samples:aspnetapp

En este ejemplo, el comando responde con el mensaje siguiente:

warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
 No XML encryptor configured. Key {d8e1e1ea-126a-4383-add9-d9ab0b56520d} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.

Esta imagen contiene una aplicación web, por lo que ahora escucha las solicitudes que llegan en el puerto HTTP 80. Pero si abre un explorador web y va a http://localhost:80, no verá la aplicación.

Docker no permite de forma predeterminada que las solicitudes de red entrantes lleguen al contenedor. Hay que indicar a Docker que asigne un número de puerto específico del equipo a un número de puerto específico del contenedor, agregando para ello la opción -p a docker run. Esta instrucción permite las solicitudes de red al contenedor en el puerto especificado.

Además, la aplicación web de esta imagen no está pensada para usarse de forma interactiva desde la línea de comandos. Cuando se inicia, la intención es que Docker la inicie en segundo plano y simplemente permita que se ejecute. Use la marca -d para indicar a Docker que inicie la aplicación web en segundo plano.

Presione Ctrl+C para detener la imagen y, después, reiniciarla como se muestra en el siguiente ejemplo:

docker run -p 8080:80 -d mcr.microsoft.com/dotnet/samples:aspnetapp

El comando asigna el puerto 80 del contenedor al puerto 8080 del equipo. Si visita la página http://localhost:8080 en un explorador, verá la aplicación web de ejemplo.

Captura de pantalla de la aplicación web de ejemplo en ejecución en un explorador.

Contenedores y archivos

Si un contenedor en ejecución realiza cambios en los archivos de su imagen, esos cambios solo existen en el contenedor donde se hayan realizado. A menos que realice pasos específicos para conservar el estado de un contenedor, estos cambios se pierden cuando se quite el contenedor. De forma similar, varios contenedores basados en la misma imagen que se ejecutan de forma simultánea no comparten los archivos de la imagen. Cada contenedor tiene su propia copia independiente. Los datos escritos por un contenedor en su sistema de archivos no son visibles para el otro.

Es posible agregar volúmenes grabables a un contenedor. Un volumen representa un sistema de archivos que puede montar el contenedor y está disponible para la aplicación que se ejecuta en el contenedor. Los datos de un volumen se conservan cuando se detiene el contenedor, y varios contenedores pueden compartir el mismo volumen. Los detalles para crear y usar volúmenes están fuera del ámbito de este módulo.

Se recomienda soslayar la necesidad de realizar cambios en el sistema de archivos de imagen de las aplicaciones implementadas con Docker. Úselo solo con archivos temporales que pueda permitirse perder.

Administración de contenedores de Docker

Puede ver los contenedores activos con el comando docker ps.

docker ps

La salida incluye el estado del contenedor (Up si se está ejecutando, Exited si ha finalizado) entre otros valores, como las marcas de línea de comandos especificadas al iniciar la imagen y otra información. Docker permite ejecutar varios contenedores de forma simultánea a partir la misma imagen, por lo que a cada contenedor se le asigna un identificador único y un nombre legible único. La mayoría de los comandos de Docker que se usan para administrar contenedores individuales pueden utilizar el identificador o el nombre para hacer referencia a un contenedor específico.

En la siguiente salida, puede ver dos contenedores. El campo PORTS muestra que el contenedor con el identificador elegant_ramanujan es la imagen que se ejecuta con el puerto 80 en el host de Docker asignado al puerto 8080 del equipo. La instancia de youthful_heisenberg es el contenedor de la ejecución anterior de la imagen. El campo COMMAND muestra el comando que el contenedor ha ejecutado para iniciar la aplicación en la imagen. En este caso, es dotnet aspnetapp.dll en ambos contenedores. El identificador de imagen para los contenedores también es el mismo, ya que los contenedores ejecutan la misma imagen.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   42 seconds ago      Up 41 seconds       0.0.0.0:8080->80/tcp   elegant_ramanujan
d27071f3ca27        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   5 minutes ago      Up 5 minutes       0.0.0.0:8081->80/tcp   youthful_heisenberg

Nota:

docker ps es un acceso directo para docker container ls. Los nombres de estos comandos se basan en las utilidades de Linux ps y ls, que enumeran los procesos en ejecución y los archivos, respectivamente.

Puede detener un contenedor activo con el comando docker stop y especificar el identificador del contenedor.

docker stop elegant_ramanujan

Si ejecuta docker ps de nuevo, verá que el contenedor elegant_ramanujan ya no aparece en la salida. El contenedor todavía existe, pero ya no hospeda un proceso en ejecución. Puede incluir los contenedores detenidos en la salida de docker ps si incluye la marca -a:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   2 minutes ago       Exited (0) 21 seconds ago                       elegant_ramanujan
d27071f3ca27        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   7 minutes ago      Up 7 minutes       0.0.0.0:8081->80/tcp   youthful_heisenberg

Puede reiniciar un contenedor detenido con el comando docker start. El proceso principal del contenedor se inicia de nuevo.

docker start elegant_ramanujan

Normalmente, cuando se detiene un contenedor, también se debe quitar. Al quitar un contenedor se limpian los recursos que deja. Una vez que quite un contenedor, los cambios realizados dentro del sistema de archivos de su imagen se perderán definitivamente.

docker rm elegant_ramanujan

No se puede quitar un contenedor en ejecución, pero se puede forzar la detención y eliminación de un contenedor con la marca -f en el comando docker rm. Es una forma rápida de detener y quitar un contenedor, pero solo se debe usar si la aplicación incluida en el contenedor no tiene que realizar un cierre estable.

docker container rm -f elegant_ramanujan

Eliminación de imágenes de Docker

Puede eliminar una imagen del equipo local con el comando docker image rm. Especifique el identificador de imagen de la imagen que se va a eliminar. En el ejemplo siguiente se quita la imagen de la aplicación web de ejemplo.

docker image rm mcr.microsoft.com/dotnet/core/samples:aspnetapp

Los contenedores que ejecuten la imagen tendrán que terminarse antes de que se pueda quitar la imagen. Si el contenedor sigue usando la imagen, obtendrá un mensaje de error como el que se muestra a continuación. En este ejemplo, el error se produce porque el contenedor youthful_heisenberg sigue usando la imagen.

Error response from daemon: conflict: unable to delete 575d85b4a69b (cannot be forced) - image is being used by running container c13165988cfe