Un contenedor es un proceso aislado que ejecuta una aplicación con su propio entorno de usuario y sus dependencias.
Tú tienes instalado el SDK de .NET 10, SQL Server Developer y una configuración específica de Windows. El servidor de producción tiene Linux, una versión antigua de las librerías y permisos restringidos. Resultado: Tu API explota al desplegar.
Docker reduce muchísimo este problema.
Docker nos permite empaquetar nuestra aplicación junto con el runtime, las librerías y la configuración de ejecución en una caja cerrada llamada contenedor. El contenedor no trae un sistema operativo completo: comparte el kernel del host, pero sí trae el entorno de usuario que necesita la app.
Si el contenedor arranca en tu máquina, tienes muchas más garantías de que arrancará igual en producción, siempre que uses la arquitectura correcta de imagen.
Hoy vamos a escribir la “receta” para crear esa caja: el Dockerfile.
El Dockerfile
El Dockerfile es un archivo de texto (sin extensión) que le dice a Docker paso a paso cómo construir tu aplicación.
Para .NET es habitual usar multi-stage builds (construcción en varias etapas). ¿Por qué?
- Para compilar el código necesitas el SDK, que incluye muchas herramientas.
- Para ejecutar la app solo necesitas la imagen de ASP.NET Core Runtime, bastante más pequeña.
No queremos llevar el compilador a producción. Así que usaremos una imagen para compilar y luego copiaremos solo el resultado a una imagen ligera.
Crear el archivo
Crea un archivo llamado Dockerfile en la raíz de tu proyecto (junto al .sln o el .csproj principal).
Contenido paso a paso
# ETAPA 1: BUILD (El constructor)
# Usamos la imagen oficial del SDK de .NET 10
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# 1. Copiamos el csproj y restauramos dependencias
# (Hacemos esto antes de copiar todo el código para aprovechar la caché de Docker)
COPY ["MiApi/MiApi.csproj", "MiApi/"]
RUN dotnet restore "MiApi/MiApi.csproj"
# 2. Copiamos el resto del código y compilamos
COPY . .
WORKDIR "/src/MiApi"
RUN dotnet build "MiApi.csproj" -c Release -o /app/build
# 3. Publicamos los archivos finales
FROM build AS publish
RUN dotnet publish "MiApi.csproj" -c Release -o /app/publish /p:UseAppHost=false
# ETAPA 2: RUNTIME (El ejecutor)
# Usamos la imagen ligera de ASP.NET Core (sin herramientas de compilación)
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
WORKDIR /app
# Exponemos el puerto (por defecto en las imágenes modernas de .NET es el 8080)
EXPOSE 8080
# Copiamos los archivos compilados desde la etapa anterior (/app/publish)
COPY --from=publish /app/publish .
# Ejecutamos como usuario no root cuando la imagen lo soporte
USER $APP_UID
# Definimos el punto de entrada
ENTRYPOINT ["dotnet", "MiApi.dll"]El archivo olvidado: .dockerignore
Igual que en Git no subes la carpeta bin ni obj, en Docker tampoco deberías copiarla al contenedor (ensucia y ralentiza la construcción).
Crea un archivo .dockerignore junto al Dockerfile:
**/.dockerignore
**/.env
**/bin/
**/obj/
**/.vs/
**/.git/Construir la imagen
Ahora que tenemos la receta, vamos a cocinar el plato. Abre la terminal en la carpeta del Dockerfile:
# -t: Tag (nombre de la imagen)
# . : El contexto (la carpeta actual)
docker build -t mi-api-web .Docker descargará las imágenes base, copiará tu código, compilará y generará una imagen llamada mi-api-web.
La primera construcción tardará más. Las siguientes pueden reutilizar las capas que no hayan cambiado, como la restauración de paquetes.
Ejecutar el contenedor
¡Hora de la verdad! Vamos a arrancar nuestra API aislada del mundo.
# -d: Detached (en segundo plano)
# -p: Puerto (PuertoMáquina : PuertoContenedor)
# --name: Nombre para identificar el contenedor
docker run -d -p 5000:8080 --name mi-api-corriendo mi-api-webEl mapeo de puertos es muy importante:
- 8080: Es donde escucha tu API DENTRO del contenedor (por defecto en las imágenes modernas de .NET).
- 5000: Es el puerto donde quieres acceder desde TU navegador.
Ahora, abre http://localhost:5000/swagger (o tu endpoint de prueba).
¡Ahí está! Tu API funcionando dentro de un entorno Linux aislado.
Visual Studio y Docker
Te he enseñado a hacerlo a mano para que entiendas el mecanismo. Pero Visual Studio lo hace por ti.
- Haz clic derecho en el proyecto y elige Add > Docker Support.
- Elige “Linux”.
Visual Studio creará el Dockerfile automáticamente e incluso configurará un botón de “Play con Docker” para que puedas depurar (poner breakpoints) dentro del contenedor.
Variables de entorno en Docker
¿Recuerdas el appsettings.json y la cadena de conexión? En Docker no queremos cambiar el archivo JSON cada vez. Usamos Variables de Entorno.
Podemos inyectar configuración al ejecutar el contenedor con -e:
docker run -d -p 5000:8080 \
-e "ConnectionStrings__DefaultConnection=Server=mi-server;Database=db..." \
-e "Logging__LogLevel__Default=Warning" \
mi-api-webEn variables de entorno usamos __ en lugar de : porque funciona mejor entre shells, sistemas operativos y contenedores. ASP.NET Core lo traduce automáticamente a secciones de configuración.