Contenedor

Creando un contenedor de Docker para una aplicación .NET

En este artículo, veremos cómo compilar e implementar un contenedor de Docker para una aplicación básica en .NET

  1. Crear proyecto para una aplicación básica en .NET
  2. Crear archivo Dockerfile
  3. Crear una imagen de Docker a partir de un Dockerfile
  4. Crear un contenedor
  5. Iniciar y detener contenedor
  6. Conectarse a un contenedor
  7. Eliminar un contenedor
  8. Ejecución única
  9. Limpiar los recursos

Crear proyecto para una aplicación básica en .NET

Creamos una aplicación de consola y la llamamos «SampleSum», usamos .NET 7.

Este código genera números aleatorios entre 1 y 9, los suma y los imprime en la consola. El bucle while se ejecuta hasta que la suma de los números generados alcance un valor máximo (si se especifica).

var sum = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;
while (max is -1 || sum < max)
{
    int num = new Random().Next(1, 10);

    Console.WriteLine($"Suma {sum} + {num} = {sum += num}");
    await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}

Crear archivo Dockerfile

Dockerfile es un archivo de texto plano que contiene una serie de instrucciones que se utilizan para construir una imagen de Docker.

Para crear Dockerfile, añadimos compatibilidad con Docker como muestra la imagen:

y elegimos Windows o Linux cuando se solicite elegir el sistema operativo. Esto crea un archivo denominado Dockerfile en el directorio que contiene el archivo .csproj 

Abrimos este archivo «Dockerfile» y vemos lo siguiente:

FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["SampleSum.csproj", "."]
RUN dotnet restore "./SampleSum.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "SampleSum.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "SampleSum.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "SampleSum.dll"]

Este Dockerfile contiene las instrucciones para construir una imagen Docker para una aplicación básica en .NET 7. Se compone de etapas, las etapas en el Dockerfile se definen usando la instrucción «FROM» y cada etapa puede tener su propio conjunto de instrucciones adicionales para construir la imagen final.

Las etapas en un Dockerfile se pueden usar para separar diferentes partes del proceso de construcción, como la instalación de dependencias, la compilación de código fuente, la configuración de la aplicación y la exposición de puertos, entre otras tareas. Esta separación en etapas ayuda a optimizar la construcción de imágenes de Docker y a reducir el tamaño final de la imagen.

Aquí hay un desglose de lo que hace cada etapa:

1. La primera etapa, llamada «base», utiliza la imagen de tiempo de ejecución de .NET Core versión 7.0 como base y establece el directorio de trabajo en /app.

// Etapa 1
FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base
WORKDIR /app

2. La segunda etapa, llamada «build», utiliza la imagen de SDK de .NET Core versión 7.0 como base, establece el directorio de trabajo en /src y copia el archivo de proyecto SampleSum.csproj al directorio actual. Luego se ejecuta el comando «dotnet restore» para restaurar cualquier paquete NuGet necesario y se copian todos los archivos al directorio /src del contenedor. Después, se compila la aplicación en modo Release y se almacenan los resultados en el directorio /app/build.

// Etapa 2
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["SampleSum.csproj", "."]
RUN dotnet restore "./SampleSum.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "SampleSum.csproj" -c Release -o /app/build

3. En la tercera etapa, llamada «publish», se establece la imagen de «build» como base y se ejecuta el comando «dotnet publish» para publicar la aplicación en modo Release, sin usar AppHost, y se almacenan los resultados en el directorio /app/publish.

// Etapa 4
FROM build AS publish
RUN dotnet publish "SampleSum.csproj" -c Release -o /app/publish /p:UseAppHost=false

4. Finalmente, en la cuarta etapa, llamada «final», se establece la imagen de tiempo de ejecución de .NET Core como «base» y se copian los archivos publicados desde la etapa «publish» al directorio /app del contenedor. Luego se establece el punto de entrada de la aplicación como «dotnet SampleSum.dll».

// Etapa 4
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "SampleSum.dll"]

Crear una imagen de Docker a partir de un Dockerfile

El comando docker build se utiliza para construir una imagen de Docker a partir de un Dockerfile.

docker build -t sum-image -f Dockerfile .

Los parámetros -t sum-image establecen el nombre de la imagen como «sum-image», lo que significa que se puedes utilizar este nombre para crear contenedores a partir de esta imagen. -f Dockerfile especifica que el archivo Dockerfile que se utilizará para construir la imagen se llama «Dockerfile». El punto al final . indica que el Dockerfile se encuentra en el directorio actual.

Ejecutamos el siguiente comando docker image ls para listar todas las imágenes de Docker que están almacenadas en el sistema local:

docker image ls

Crear un contenedor

Ahora que tenemos una imagen que contiene la aplicación, podemos crear un contenedor docker create:

docker create --name sum-container sum-image

El comando docker create anterior creará un contenedor basado en la imagen «sum-image». La salida de ese comando muestra el valor CONTAINER ID.

Para ver una lista de todos los contenedores, use el comando docker container ls:

docker container ls -a

Iniciar y detener contenedor

El contenedor se creó con un nombre sum-container, usado para administrar el contenedor.

Iniciamos el contenedor con docker start y luego se usa el comando docker ps para mostrar solo los contenedores que están en ejecución:

docker start sum-container
docker ps

De manera similar, el comando docker stop detendrá el contenedor.

docker stop sum-container

Conectarse a un contenedor

Una vez que se ejecuta un contenedor, podemos conectarnos a él para ver la salida.

Usamos comando docker attach para iniciar el contenedor y echar un vistazo al flujo de salida:

docker attach sum-container

Eliminar un contenedor

Si el contenedor está en ejecución, lo detenemos:

docker stop sum-container

Luego, se usa el comando docker rm para eliminar el contenedor:

docker rm sum-container

Comprobamos que se ha eliminado, listando contenedores:

docker container ls

Ejecución única

Docker proporciona el comando docker run para crear y ejecutar el contenedor como comando único. Este comando elimina la necesidad de ejecutar docker create y luego docker start. También podemos establecer este comando para que elimine automáticamente el contenedor cuando este se detenga. Por ejemplo, use docker run -it --rm para hacer dos cosas: primero, use automáticamente el terminal actual para conectarse al contenedor y cuando el contenedor finalice, quítalo:

docker run -it --rm sum-image

El contenedor también pasa parámetros a la ejecución de la aplicación .NET. Para indicar a la aplicación .NET que sume solo hasta superar 30, pase 30 y se detendrá el proceso que está ejecutándose en el contenedor:

docker run -it --rm sum-image 30

Cambio de ENTRYPOINT, con el comando docker run también permite modificar el comando ENTRYPOINT desde el archivo Dockerfile y ejecute algún otro elemento, pero solo para ese contenedor:

docker run -it --rm --entrypoint "cmd.exe" sum-image

Limpiar los recursos

Eliminar contenedor contenedor (docker rm):

docker stop sum-container
docker rm sum-container

Eliminar la imagen (docker rmi):

docker rmi sum-image

Enlaces

Introducción a Docker y contenedores

Comandos de Docker