Asp.Net Core – solucionar error al publicar en docker (assembly not found)

Buenas! Imagina que tienes una aplicación hecha en Asp.Net Core y que referencia al metapaquete Microsoft.AspNetCore.All. También tienes un Dockerfile y un fichero compose para generar la imagen usando una multi-stage build.

La imagen se genera sin problemas pero al ejecutarla recibes un error y no arranca.

El Dockerfile puede ser similar al que sigue (nota: es el Dockerfile generado por defecto por VS2017 15.5.4 al agregar soporte para Docker):

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY *.sln ./
COPY CrashOnStartup/CrashOnStartup.csproj CrashOnStartup/
RUN dotnet restore
COPY . .
WORKDIR /src/CrashOnStartup
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

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

No tiene mucha complicación. Es un fichero multi-stage y realiza lo siguiente:

  1. Parte de la imagen base microsoft/aspnetcore:2.0.
  2. Usa la imagen microsoft/aspnetcore-build:2.0 como imagen de build
  3. En esta imagen realiza el dotnet restore, build y publish
  4. Recoge el resultado del publish y lo copia en la imagen base para generar el contenedor final.

El error que puedes obtener es el siguiente:

Error:
  An assembly specified in the application dependencies manifest (CrashOnStartup.deps.json) was not found:
    package: 'Microsoft.AspNetCore.Mvc.Abstractions', version: '2.0.2'
    path: 'lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Abstractions.dll'
  This assembly was expected to be in the local runtime store as the application was published using the following target manifest files:
    aspnetcore-store-2.0.5.xml

¿Qué está ocurriendo? Pues bien lo que ocurre es que cuando se ha publicado tu aplicación no se están publicando las dependencias correspondientes de ASP.Net Core. Recuerda que, por defecto, en ASP.Net Core 2 al usar dotnet publish no se publican los ensamblados de ASP.Net Core 2, solo los de tu aplicación y ensamblados adicionales. La razón es que se presupone que todos los ensamblados de ASP.Net Core 2 existen en cualquier máquina que tenga el runtime instalado (en lo que llamamos el runtime store).

La primera opción que te puede venir a la mente es que la imagen microsoft/aspnetcore:2.0 no tenga la runtime store, por lo que debamos publicar no solo nuestros ensamblados si no todos los del runtime al publicar nuestra aplicación. Pero no, no es esoDicha imagen SÍ tiene la runtime store¿Entonces? ¿Qué está ocurriendo?

Pues algo muy sencillo: la versión que tienes de la imagen microsoft/aspnet-core NO se corresponde con la versión del metapaquete que estás usando. Es decir si referencias al metapaquete Microsoft.AspNetCore.All en su versión 2.0.5 debes usar la imagen que tiene el runtime en su versión 2.0.5.

La razón por la que puedes tener la imagen desactualizada es que el tag 2.0 que se usa es un tag «flotante». Eso significa que es un tag que se mueve a medida que se van añadiendo nuevas versiones de dicha imagen. P. ej. en el momento de redactar este post el tag 2.0 contiene la imagen con la versión 2.0.5 (en ambas imágenes). Pero cuando salga la 2.0.6 el tag 2.0 se promocionará para que apunte a dicha imagen. La idea es que el tag 2.0 apunta «a la última imágen 2.0 en todo momento».

Pero el tema está en que docker no refresca automáticamente las imágenes. Es decir imagina que te descargaste la imagen microsoft/aspnetcore:2.0 en tu sistema pero cuando el tag apuntaba a la imagen 2.0.4. Posteriormente sale la versión 2.0.5 y Microsoft actualiza el tag 2.0 para que apunte a la 2.0.5. Luego usas VS (que tienes debidamente actualizado) para crear un proyecto nuevo y este proyecto usa el metapaquete en su versión 2.0.5. Y con eso creas la imagen de Docker. Y aquí obtendrás el error, porque TU imagen microsoft/aspnetcore:2.0 (que ya tenías en local) es la versión 2.0.4. A pesar de que el tag se haya promocionado, Docker no refresca la imagen porque, por lo que el respecta, la versión 2.0 ya la tienes en tu máquina.

La solución es forzar a Docker que te refresque la imagen usando:

docker pull microsoft/aspnetcore:2.0

Luego reconstruyes la imagen y ya te debería funcionar todo.

Por lo tanto la moraleja es: cuidado con los tags flotantes, ¡que debes «actualizarlos» a mano!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *