Índice
Para este post vamos a ver una pequeña introducción a Docker, veremos que es Docker. Qué diferencia Docker de una máquina virtual, y por supuestos los beneficios que nos trae Docker. Finalmente veremos cómo instalar Docker y un pequeño ejemplo.
1 - Qué es Docker
Docker es una plataforma que nos permite simplificar procesos para construir aplicaciones, distribuirlas y además nos permite ejecutaras en distintos entornos y sistemas.
Con entornos me refiero a entorno o servidor de desarrollo, preproducción y producción.
Pero no únicamente el entorno puede variar, sino que además el sistema del propio entorno, es común tener nuestro ordenador de desarrollo con windows o mac, mientras que los servidores suelen ser en su gran mayoría linux, así como AWS, google cloud, incluso azure corre su propia versión de linux.
1.1 - Cómo funciona Docker
Cuando hablamos de Docker realmente hablamos de dos conceptos, Imágenes
, y contenedores
, estos dos conceptos es en los que se basa Docker.
Si te has fijado en el logo de Docker, la ballena tiene varios contenedores encima, y esto es así por el siguiente motivo.
El poder de los contenedores reside en que nos ayudan a hacer despliegues de una forma mucho más sencilla.
Si pensamos hace unos años para hacer un despliegue de una aplicación grande, consumimos mucha cantidad de tiempo, había que ir a cierta carpeta en X servidor borrarla a mano, luego mover los ficheros, etc. Por supuesto este tipo de acciones se podían hacer con scripts, pero no todas las empresas utilizan scripts.
Básicamente cada empresa y cada desarrollador lo hace de una forma diferente.
Docker nos proporciona una técnica consistente a la hora de hacer estos despliegues en diferentes entornos, lo cual nos proporciona un gran número de beneficios para nosotros los desarrolladores.
1.2 - Qué es una imagen de Docker
Como he mencionado anteriormente Docker se basa en dos conceptos, imágenes y contenedores, cuando hablamos de imágenes hablamos de “algo” que se utiliza para construir un contenedor.
Una imagen contendrá los ficheros necesarios para correr la aplicación que queremos correr en un servidor en concreto. Por ejemplo ubuntu o windows.
Después tenemos nuestro framework, o la base de datos, los ficheros, etc.
En nuestro caso en concreto, si tenemos una web escrita en ASP.NET
tenemos el framework escrito en la imagen así como el código de la imagen.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /home/app
COPY bin/Debug/netcoreapp3.1/publish .
ENTRYPOINT ["dotnet", "WebPersonal.BackEnd.API.dll"]
Docker no descarga todas las librerías del sistema operativo, si no que es una forma de indicar sobre que servidor queremos que se ejecute. Para nuestro caso en concreto únicamente se descargarán las librerías de Net Core
.
La imagen como tal por sí sola no hace nada, sino que es la definición que es utilizada para conseguir un contenedor que se ejecute.
1.3 - Qué es un contenedor de Docker
Si nos basamos en el punto anterior, podemos ver que un contenedor es la instancia de la imagen, donde la aplicación está corriendo.
Puede ser cualquier tipo de aplicación, desde nuestra propia aplicación web, como un servidor de caché, o una base de datos.
El gran beneficio de utilizar contenedores es que cada contenedor está completamente aislado del resto de contenedores, lo que implica que cada uno puede ser creado, instanciado, parado, o eliminado individualmente.
Otro de los grandes beneficios es que es muy rápido y sencillo crear un contenedor.
2 - Diferencia entre un contenedor Docker y una máquina virtual
Cuando empezamos a desarrollar en Docker, lo primero que nos viene a la mente son las máquinas virtuales, que hemos tratado con ellas durante nuestros estudios en la universidad o en los grados, porque visto el punto anterior, parece lo mismo, es una máquina, que contiene un sistema operativo y una aplicación dentro.
Lo primero es que una máquina virtual corre en nuestro sistema operativo como “invitado” a través del Hypervisor, además correr múltiples máquinas virtuales, depende del tamaño de nuestro disco duro, o nuestra memoria puede ser una locura. Ya que funcionan, pero necesitas cierta cantidad importante de ram, procesador, y por supuesto unos cuantos gigas en el disco duro, etc.
Por el contrario los contenedores de Docker corren sobre el motor de Docker, el cual se ejecuta directamente sobre el sistema operativo. Lo que implica que el tamaño es mucho mas pequeño que una máquina virtual normal.
Un contenedor Docker, contiene por sí solo, todos los ficheros de sistema que necesita la aplicación que va a ejecutar para que esta corra sin problemas. pero a su vez, no contiene ninguno adicional que no necesite.
Por supuesto como son contenedores individuales, los ficheros del contenedor 1 no tienen nada que ver con los del contendor de la app2. por ejemplo, podemos crear la app1 en .net y la app2 en JavaScript.
Más adelante en otro post veremos como hacer un contenedor con una base de datos para nuestros test de integración.
3 - Ejecutar una aplicación web en Docker
Para este ejemplo voy a ejecutar la aplicación web que estoy creando para el curso de Web C#.
Para ello únicamente debemos crear un fichero que se llame Dockerfile, Dejaré la explicación del contenido del fichero para un post únicamente para ello.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /home/app
COPY bin/Debug/netcoreapp3.1/publish .
ENTRYPOINT ["dotnet", "WebPersonal.BackEnd.API.dll"]
Lo que debemos saber para este post es que la aplicación web corre sobre ASP .NET Core 3.1
por lo que deberemos indicarlo en el apartado FROM
.
Indicamos el directorio de trabajo de nuestro Docker, recordamos que es LINUX e indicamos que copie los ficheros de la carpeta publish, previamente hacemos dotnet publish
en powershell.
Finalmente indicamos el punto de entrada, el cual es el .dll
de nuestra API.
posteriormente construimos nuestra imagen de Docker y la corremos en su contenedor.
docker build -t webpersonal .
Al ejecutar el comando de Docker descargara todos los ficheros necesarios para la ejecución de la aplicación.
Ahora, corremos nuestro contendor con el siguiente comando:
docker run -p 8080:80 webpersonal
Y vemos como la aplicación está escuchando en el puerto 8080 y podemos hacer llamadas a la API sin ningún problema. Para el ejemplo he creado un endpoint.
[ApiController]
[Route("api/[controller]")]
public class HealthController : ControllerBase
{
[HttpGet("ejemplo-docker")]
public string Get()
{
Console.WriteLine("docker");
return "true";
}
}
Como hemos visto en el código de la api tenemos un Console.WriteLine(“Docker”);
esto es porque si vamos al dashboard de Docker (en el icono de la barra de tareas) podemos ver la ejecución del contenedor.
Así como cierta información o por ejemplo la habilidad de parar/borrar los contenedores. Comúnmente realizaremos todas estas acciones desde la línea de comandos.
4 - Beneficios de Docker
El primer beneficio y el más claro de todos es que mantiene el entorno original limpio. Pero que quiero decir con esto.
Por ejemplo para ejecutar un aplicación que contiene una aplicación web escrita en node js
, una aplicación de consola escrita en .net
y ambas se conectan con una base de datos mysql
.
En circunstancias normales, deberíamos instalar .net en el sistema operativo, junto con Docker, junto con la base de datos; Pero si utilizamos Docker, lo único que necesitamos es un sistema capaz de ejecutar Docker, y crearemos un contenedor que contenga .NET con la aplicación de consola de .NET. Un contenedor con node para la aplicación web, y un contenedor con la base de datos.
Debido a que cada contenedor se ejecuta de una forma independiente, cualquier usuario que ejecute el contenedor o si lo ejecutamos en un servidor recibirá el mismo resultado, con lo que el problema de “en mi ordenador funciona” ya no nos pasará.
Incluso en cantidad de ocasiones, como puede ser con amazon web services, desarrollaremos en nuestra máquina local en Visual Studio, pero a la hora de hacer un despliegue lo haremos sobre ECS que es básicamente Docker.
5 - Instalación de Docker
Primero de todo indicar que vamos a tratar con Docker for windows, ya que Docker para windows no es exactamente igual a Docker para linux y mac.
En caso de que seas usuario de linux o mac, Docker tiene buenos tutoriales de como ser instalado. El proceso para mac es similar, ya que también necesitas una máquina virtual, pero para linux puede ser ejecutado de forma nativa.
5.1 - Docker en windows
Básicamente lo que hacemos es correr un pequeño Docker, en nuestro windows, pero no nos sirve cualquier windows, debe tener las siguientes características
- Windows 10
- 64 Bits
- Versión home, pro o enterprise
- Actualización Mayo 2021: Docker para windows también esta disponible para la version windows home.
Si has instalado anteriormente Docker toolbox o Docker machine previamente puede dar a fallos, así que recomiendo desinstalarlo.
Docker para windows no está recomendado para su uso en producción, para ello hay que irse a la versión de linux; Los comandos son iguales, lo único es que permite escalabilidad y algunas funcionalidades más, desde el equipo de Docker valoran más que sea estable a que tenga mayor número de funcionalidades.
Docker para windows corre en Linux, dentro de una máquina virtual Hyper-V;
Pero tenemos que tener claro, que esto nos permite ejecutar comandos de Docker en powershell y que funcionen de una forma correcta, lo cual es alucinante.
5.2 - Instalar Docker en Windows
Primero debemos tener instalado Hyper-v
porque existen otros métodos para instalar docker que no utilizan hyper-v pero te llenan el pc de un montón de instalaciones adicionales y además no funciona correctamente.
Para instalar Hyper-V tenemos que tener windows 10 pro o enterprise.
Una vez tenemos windows 10 pro, vamos al panel de control -> programas y caracteristicas -> activar o desactivar características de windows
Ahí buscamos la carpeta donde indica “Hyper-V
” y la pulsamos.
Al pulsar en ok nos instalará Hyper-v.
5.2.1 - Posibles problemas de Docker en Windows
Algunas veces, esto no es suficiente, y cuando reiniciamos el PC nos dice que no puede ejecutar Docker.
Uno de los casos más comunes es porque debemos habilitar en la bios la funcionalidad de “hardware virtualization machine” denominadas “Intel VT/VT-x
” o “AMD-V
”.
Ademá debemos asegurarnos que “Second level address translation” (SLAT) y “Data execution protection” también están habilitados.
5.3 - Descargar e instalar Docker para windows
Una vez hemos llegado a este punto todo lo que nos queda es ir a la web de Docker y descargamos la version que necesitamos para nuestra máquina, eligiendo siempre la versión estable e instalamos.
Una vez instalado veremos que Docker está disponible en la barra de tareas, ese pequeño icono de la ballena.
Podemos pulsar sobre él y nos abre la interfaz pero, yo personalmente llevo trabajando con Docker más de un año y no he abierto la interfaz ni una sola vez. Todo lo que nos interesa es la línea de comandos.
Para comprobar si Docker está correctamente instalado, abrimos powershell y ejecutamos el comando docker version
el cual nos dará una respuesta similar a la siguiente:
Client: Docker Engine - Community
Version: 19.03.8
API version: 1.40
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:23:10 2020
OS/Arch: windows/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.8
API version: 1.40 (minimum version 1.12)
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:29:16 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
Como vemos nos indica que el cliente está corriendo en windows, pero el servidor de Docker corre en linux, eso es por la máquina virtual Hyper-V que hemos instalado en el punto 5.2.
Conclusión
El uso de Docker tanto durante el desarrollo de nuestras apliaciones como a la hora de hacer los despliegues a producción es muy útil, ya que nos simplifica la vida una barbaridad.
En C# ya que el propio Visual Studio compila y te permite debuggear las aplicaciones de una forma efectiva no es tan necesario, pero en otros lenguajes como php nos permite ahorrarnos el tener que instalar php+apache en el entorno de desarrollo.
Hacer los test dentro de Docker, nos asegura un entorno cerrado y controlado para el correcto funcionamiento de los mismos.