¿Cómo desplegar aplicaciones con Docker y publicar imágenes?

Como desplegar aplicaciones con Docker y publicar imagenes
Inicio » Informática » Varios » ¿Cómo desplegar aplicaciones con Docker y publicar imágenes?

Tabla de contenido

Para desplegar aplicaciones con Docker y publicar imágenes ha sido necesario estudiar a lo largo de este curso de Docker los siguientes tutoriales:

Ahora es el momento de dar el último paso, publicar tus imágenes de Docker para que cualquiera pueda descargarlas y desplegar tu aplicación para que los usuarios puedan utilizarla.

¿Cómo publicar imágenes en Docker Hub con comandos?

Para publicar una imagen utilizaremos Docker Hub que, al igual que GitHub, nos permite crear repositorios de imágenes de nuestros proyectos. Pueden ser públicos o privados.

Los pasos para publicar una imagen en Docker Hub son:

  • Inicia sesión en Docker Hub o créate una cuenta si no la tienes.
  • Ve al menú y selecciona el apartado “Repositories”.
  • Selecciona “Create repository” y dale un nombre descriptivo. Es en esta sección donde puedes establecer si es público o privado.
  • Apunta el nombre completo del repositorio, en nuestro caso es “codearconet/my-app-image”.
  • Lista las imágenes que tienes y, para la imagen que quieras publicar, asígnale el mismo nombre del punto anterior con el comando image tag antiguo-nombre:etiqueta nuevo-nombre:etiqueta.
  • Inicia sesión en la consola con el comando docker login.
  • Sube la imagen a Docker Hub con el comando docker push codearconet/my-app-image:1.0.0.
  • Verifica que la imagen se ha subido correctamente a través de la pestaña “Tags”.
  • Si quisieras subir otra versión/tag lo único que tendríamos que hacer sería crearla en nuestra terminal con el comando build y una etiqueta distinta y, después, hacer push. Podemos comprobarlo en la siguiente captura:

¿Cómo generar imágenes Docker privadas en local?

Si no quieres utilizar Docker Hub una alternativa para compartir imágenes Docker es utilizar el comando docker image save, en nuestro caso utilizaremos docker image save -o my-app-image-100.tar my-app-image:1.0.0.

Esto lo que hace es crear un fichero comprimido en el directorio en el que te encuentres para después compartirlo con otras personas de manera totalmente privada.

Para crear la imagen a partir del fichero .tar generado anteriormente utilizaremos el comando docker image load -i fichero.tar, en nuestro caso sería docker image load -i my-app-image-100.tar.

Como puedes observar es un proceso sumamente sencillo para generar imágenes en local y enviárselas a compañeros sin necesidad de pasar por una plataforma externa en la nube.

Formas y servicios para desplegar aplicaciones Docker

Existen varias formas para desplegar aplicaciones Docker con múltiples contenedores, entre ellas encontramos:

  • Kubernetes, como ya comentamos, nos permitirá desplegar nuestro conjunto de contenedores en múltiples servidores. Es una herramienta tan grande y compleja que queda fuera del ámbito de este curso.
  • Docker Swarm, alternativa similar a Kubernetes.
  • Despliegue manual, donde simplemente tendremos un servidor en el que descargaremos nuestras imágenes y haremos un docker compose up para desplegar la aplicación. Es el que veremos en los apartados siguientes.

Además de lo anterior, podemos desplegar aplicaciones Docker en los siguientes servicios o proveedores:

  • AWS o Amazon Web Services.
  • Azure.
  • Google Cloud.
  • Digital Ocean.

Un punto importante a tener en cuenta es que docker-compose.yml es para utilizarlo en local, no se utiliza tanto en despliegues reales, para ello deberíamos utilizar cosas más complejas como Kubernetes. No obstante en los ejemplos que veremos a continuación sí que lo utilizaremos, pero recuerda, en proyectos reales no se suele utilizar mucho.

El fichero docker-compose.yml que utilizaremos es el que os enlazo y que está hospedado en el Github de nuestro proyecto Docker de ejemplo.

Pasos previos para desplegar aplicaciones en la nube

Los pasos previos necesarios para desplegar docker-compose.yml en cualquier plataforma son los siguientes:

  • Reformatear el fichero, eliminar las comillas de cualquier valor que aparezca en el fichero.
    Si no realizamos estas correcciones no podremos desplegar contenedores a la nube como, por ejemplo, a Azure ya que éste lanzará errores relativos al formato del fichero docker-compose.yml.
    --> Sustituiremos las líneas similares a esta:
    ACCEPT_EULA: "Y"
    
    --> Por la misma línea pero sin comillas dobles:
    ACCEPT_EULA: Y
    
    --> También debemos corregir la línea de healthcheck para que aparezca en una sola línea, sin saltos:
    healthcheck:
        test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P myStrongP@ssword -C -b -Q \"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'\""]
  • Subir las imágenes a Docker Hub de nuestra APP y API y reemplazarlo en el docker-compose.yml. Podéis utilizar las que ya tengo subidas (codearconet/app:1.0.0 y codearconet/api:1.0.0) o utilizar las vuestras propias.
    Una vez publicadas reemplazaremos las líneas de build por líneas de image con el nombre de la imagen subida.
    Con este punto conseguimos un paso bastante importante a la hora de desplegar y es que no será necesario hacer el build o construir la imagen y, por lo tanto, el proceso será muchísimo más rápido.
    api:
        build: ./Api/Api
    app:
        build: ./App/App
    api:
        image: codearconet/api:1.0.0
    app:
        image: codearconet/app:1.0.0

Desplegar docker-compose.yml en AppServices de Azure

Antes de comenzar debes tener en cuenta un punto importante y es que AppService de Azure no tiene soporte para volúmenes con docker-compose.yml. ¿Qué significa esto? Que nuestra base de datos no tendrá almacenamiento persistente, alternativas que podemos tomar:

  • Olvidarnos del almacenamiento persistente para este ejemplo y comentar, dentro de docker-compose.yml, las líneas de los volúmenes, tanto en el servicio de base de datos como en el apartado volumes.
  • Crear una base de datos en cualquier sitio (por ejemplo en un servidor propio o en Azure SQL Database) y cambiar la cadena de conexión en el apartado environment del servicio db.
    Es la opción recomendada, en las aplicaciones reales las bases de datos no se deben desplegar en un contenedor con un volúmen, sino a parte.

En nuestro caso implementaremos ambas opciones.

Ahora si, los pasos para desplegar docker-compose.yml en AppService de Azure son:

  • Creamos una aplicación web en AppServices. Selecciona la  opción “Contenedor” de tipo Linux.
    También es muy importante seleccionar un plan de precios adecuado, como mínimo B2 ó B3, de lo contrario la base de datos SQL Server no se iniciará y te dará bastantes problemas por falta de memoria RAM.
  • Ingresamos al AppService y dentro del apartado “Centro de implementación” seleccionamos como tipo de contenedor “Docker Compose”, origen del registro “Docker Hub” y “Público”. Además debemos seleccionar, dentro de “Config”, nuestro fichero docker-compose.yml. Guardamos los cambios.
  • Vamos a los registros del centro de implementación y esperamos a que se descarguen las imágenes y se inicien los contenedores:
  • Tras esperar un rato a que todo se inicie correctamente podemos observar que nuestra aplicación funciona como esperábamos excepto por el almacenamiento persistente:

Docker, AppServices y almacenamiento persistente

En proyectos reales no es buena idea desplegar un motor de base de datos en un contenedor y, mucho menos, sus datos en volúmenes. Esto lo hemos hecho únicamente con fines didácticos.

Es por ello que en este apartado vamos a crear una base de datos externa con Azure SQL Server y cambiar las configuraciones necesarias en nuestro proyecto para tener almacenamiento persistente con AppService y docker-compose.yml:

  • Creamos base de datos SQL de Azure, asegúrate de utilizar “Autenticación de SQL” y de guardar el usuario y la contraseña:
  • Asegúrate también de darle un nombre, seleccionar el entorno de carga de trabajo adecuado (en nuestro caso hemos seleccionado “Implementación”) y, finalmente selecciona la serie y recursos adecuados (dado que es con fines didácticos la serie más baja y ajustada sería suficiente, no ocurre lo mismo con AppService que había que aumentar el plan por temas de memoria RAM).
  • Después cambia la cadena de conexión en el API por la que aparece en el apartado “Configuración”, “Cadenas de conexión”, apartado “ADO.NET (autenticación de SQL)”. Es muy importante utilizar exactamente la cadena de conexión que proporciona Azure modificando solo la password, sin alterar parámetros porque muy posiblemente no te funcionará.
    api:
        image: codearconet/api:1.0.0
        # ports:
        #     - 50000:8080
        environment:
            #- ConnectionStrings__DefaultConnection=Server=tcp:codearcodatabase.database.windows.net,1433;Initial Catalog=Employees;Persist Security Info=False;User ID=codeArcoUser;Password=password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
  • Después comenta el apartado service db dentro del docker-compose.yml y los volúmenes porque ahora nosotros no vamos a crear ni desplegar la base de datos, ésta es externa.
  • Acude a la configuración de “Seguridad”, “Redes” y permite el acceso público, para ello crea una “Regla de firewall” y permite desde la ip “0.0.0.0” hasta “255.255.255.255”.

Una vez hecho todo lo anterior puedes acceder a la aplicación para corroborar que funciona correctamente y, de manera adicional, a través de SQL Server Management Studio puedes verificar que se insertan y eliminan datos.

La ventaja en este caso es que los datos si son persistentes y, además, desplegar los contenedores nos lleva mucho menos tiempo, nos hemos quitado la parte más pesada. De hecho este apartado podemos verlo como otra optimización de Docker.

Azure container instances ACI y docker-compose.yml

Azure container instances ACI es un servicio que permite desplegar contenedores con sus imágenes en la nube, no obstante Docker Compose ya no tiene soporte para ACI. Esto significa que si seguimos algún tutorial de docker-compose.yml y ACI los comandos no funcionarán y no vamos a poder crear los contenedores simplemente con nuestro fichero y el comando docker compose up, a parte de los pasos previos necesarios.

Como consecuencia de lo anterior tendremos que crear un complejo y elaborado fichero .json y comandos de Azure en vez de utilizar y ejecutar nuestro fichero.

Dado que esto tiene que ver más con Azure que con lo que estamos viendo, no aporta mucho valor al curso de Docker, lo vamos a dejar aparcado, simplemente lo comento porque intenté hacerlo y me dí cuenta que actualmente no se puede.

¿Cómo desplegar aplicaciones en máquinas virtuales?

Ahora vamos a seguir otro proceso completamente distinto, vamos a desplegar nuestra aplicación en una máquina virtual de Azure, aunque puede ser de cualquier otro proveedor. La desventaja principal de una máquina virtual son las dificultades a la hora de escalar los recursos cuando la demanda aumenta.

Los pasos para desplegar docker-compose.yml en una máquina virtual de Azure son:

  • Crea una máquina virtual de Azure, asegúrate de que tenga todos los puertos de entrada abiertos, de descargar la clave privada SSH, de apuntar el usuario y de que tenga al menos 3 ó 4GB de memoria RAM. El resto de opciones las dejaremos por defecto:
  • Conéctate a la máquina virtual a través del método que prefieras, en mi caso utilizaré Putty con SSH.
  • Transfiere el fichero docker-compose.yml a la máquina virtual a través del método que consideres oportuno, en mi caso utilizaré la herramienta pscp que viene con Putty, para lo cual introduciré el siguiente comando en el directorio de mi local donde se encuentra el fichero:
    pscp -scp -i C:\your_privateKey.ppk docker-compose.yml your_vm_user@your_vm_ip:/home/your_vm_user
  • Dentro de la máquina virtual ejecutamos el comando sudo apt-get update.
  • Instala Docker en la distribución de Linux que tengas a través del tutorial enlazado.
  • Si te aparece el error “Cannot connect to the Docker daemon” busca las formas de solucionarlo, en mi caso tuve que ejecutar el comando sudo service docker start.
  • Dentro de la carpeta donde hemos copiado nuestro fichero docker-compose.yml ejecuta el comando sudo docker compose up. Espera a que se levanten los contenedores:
  • Cambia el puerto por el que se inicia la aplicación. Observa que la aplicación se está levantando por el puerto 8080 de la máquina virtual pero ésta solo tiene abierto el puerto 80, tenemos que modificar el fichero y cambiar el puerto de la máquina anfitrión de la app por el 80. Para modificar el fichero utiliza el comando nano docker-compose.yml:
  • Reinicia los contenedores. Utiliza los comandos docker compose down para parar y eliminar los contenedores y docker compose up para levantar los contenedores con la nueva configuración.
  • Accede a la url “ip_maquina_virtual:80” desde tu ordenador y comprueba que la aplicación es accesible y funciona correctamente.

Ten en cuenta que también puedes (y de hecho es aconsejable) crear la base de datos externa como antes, cambiar la cadena de conexión en el fichero compose y comentar todas las líneas de la base de datos y volúmenes. Con ello conseguirás que tu máquina virtual ocupe menos espacio y necesite menos recursos (como memoria RAM) ya que no será necesario hospedar un SQL Server completo.

Como has podido ver existen muchas formas de desplegar aplicaciones con contenedores en la nube, de hecho las hay mucho mejores y elaboradas que las que hemos visto aquí como, por ejemplo, Kubernetes. No obstante, creo que es suficiente con lo que hemos visto. Ahora te toca a tí intentar desplegar en otros servicios como Digital Ocean o Amazon Web Services.

También sería una buena práctica el intentar automatizar todo esto con algun sistema DevOps como, por ejemplo, Azure pipelines o Github Actions de tal manera que, cuando alguien haga commit en el repositorio de código se generen automáticamente las imágenes, se publiquen y se actualicen en los contenedores que has creado. Dado que esto no tiene que ver directamente con el curso que estamos viendo os lo dejo como práctica extra.