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

 ·  ☕ 4 min  ·  ✍️ eiximenis

    Nota: Este post ha sido importado de mi blog de geeks.ms. Es posible que algo no se vea del todo "correctamente". En cualquier caso puedes acceder a la versión original aquí

    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 eso. **Dicha 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!

    Si quieres, puedes invitarme a un café xD

    eiximenis
    ESCRITO POR
    eiximenis
    Compulsive Developer