c# IronPdf shuts down .NET 6 Web API under Linux Docker

2.5k Views Asked by At

Versions

  • Separate .NET 6.0 Web API for PDF export
  • IronPdf.Linux - 2022.5.5629
  • IronPdf.Native.Chrome.Linux - 2022.5.5618

As of the date of writing the latest IronPdf Linux NuGet packages
enter image description here

Problem

When I ran the .NET 6 Web API under Docker Linux Container the app shuts down itself when I hit the first method from IronPdf this.pdfRenderer.RenderHtmlAsPdfAsync. There is no error or going into the catch block, simply the app stops and I have to run it again.

What have I tried? Code

I am following the official documentation provided by IronPdf: https://ironpdf.com/docs/questions/docker-linux/

Here is my usecase and how I use IronPdf library:

[HttpGet]
[Route("Reporting/PDF/{reportItemId:int}"]
public async Task<IActionResult> GenerateReport(int reportItemId)
{
    try
    {
        IronPdf.Logging.Logger.EnableDebugging = true;
        IronPdf.Logging.Logger.LogFilePath = "Default.log"; //May be set to a directory name or full file
        IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All;

        IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Disabled;
        Installation.LinuxAndDockerDependenciesAutoConfig = false;
        IronPdf.Installation.Initialize();

        ReportItemViewModel reportItemViewModel = this.reportingManager.GetReportItemById(reportItemId); // Internal Logic
        List<PdfDocument> pdfDocs = new List<PdfDocument>();

        foreach (int itemsectionId in reportItemViewModel.ReportItemSectionIds)
        {
            PdfDocument pdfDocument = await CreatePDFDocument(itemsectionId);
            
            pdfDocs.Add(pdfDocument);
        }

        PdfDocument mergedPdfs = IronPdf.PdfDocument.Merge(pdfDocs);

        await AddFooterToPdfDocument(mergedPdfs);
        
        // ... getting mergedPdfs.Stream and uploading it

        return Ok();
    }
    catch (Exception ex)
    {
        this.diagnosticService.AddErrorLog(ex: ex, accountId: accountId, employeeId: employeeId);
        return BadRequest(ex.Message);
    }
}

In the code snippet above I've included the suggested Automatic Dependency Installation, Disable GPU Acceleration and "Ahead of Time" Initialization as stated in the IronPdf librabary.

The first method to be called from IronPdf librabry is inside the CreatePDFDocument method - await this.pdfRenderer.RenderHtmlAsPdfAsync:

private async Task<PdfDocument> CreatePDFDocument(int itemsectionId)
{
    try
    {
        this.pdfRenderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
        this.pdfRenderer.RenderingOptions.PrintHtmlBackgrounds = true;
        this.pdfRenderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;

        this.pdfRenderer.RenderingOptions.MarginLeft = 6.35;
        this.pdfRenderer.RenderingOptions.MarginRight = 6.35;
        this.pdfRenderer.RenderingOptions.MarginBottom = 12;

        this.pdfRenderer.RenderingOptions.Timeout = 120;
        this.pdfRenderer.RenderingOptions.HtmlHeader = new IronPdf.HtmlHeaderFooter
        {
            HtmlFragment = await this.viewRenderer.ConvertToStringAsync("Reports/_Header", itemsectionId)
        };

        string viewAsString =
           await this.viewRenderer.ConvertToStringAsync("Reports/ReportContainer", itemsectionId);

        PdfDocument pdfDocument = await this.pdfRenderer.RenderHtmlAsPdfAsync(
              viewAsString,
              new Uri(this.BaseUrl));

        return pdfDocument;
    }
    catch (Exception ex)
    {
        this.diagnosticService.AddErrorLog(ex: ex, accountId: account.Id, employeeId: employeeId);
        throw;
    }
}

When we hit the await this.pdfRenderer.RenderHtmlAsPdfAsync method the app simply shuts down. We don't go in the catch block or throw error somewhere. I've tried to pass it very simple HTML like <div><h1>Hello World, from IronPdf under Docker Linux</h1></div> and the app shuts down again.

Note: With the code flow given above, I've successfully extracted hundreds of PDFs. The problem only arises when trying to build and run the project with a Linux Docker image.

Docker configuration

Right-clicking on the project and selecting Add -> Docker support... -> Target OS -> Linux creates the needed Dockerfile.
enter image description here

I am modifying the Dockerfile to match what IronPdf support provided in the link above. I am trying the one provided under the section Debian Linux DockerFiles -> Debian 11 with .NET 6.

# base runtime image (Debian 11 w/ .NET6 runtime)
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 1433
EXPOSE 3306
# install necessary packages
RUN apt update \
    && apt install -y libgdiplus libxkbcommon-x11-0 libc6 libc6-dev libgtk2.0-0 libnss3 libatk-bridge2.0-0 libx11-xcb1 libxcb-dri3-0 libdrm-common libgbm1 libasound2 libxrender1 libfontconfig1 libxshmfence1
# update write permissions
RUN chmod 777 .
# base development image (Debian 11 w/ .NET6 SDK)
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
# restore NuGet packages
COPY ["Example.Export/Example.Export.csproj", "Example.Export/"]
RUN dotnet restore "Example.Export/Example.Export.csproj"
# build project
COPY . .
WORKDIR "/src/Example.Export"
RUN dotnet build "Example.Export.csproj" -c Release -o /app/build
# publish project
FROM build AS publish
RUN dotnet publish "Example.Export.csproj" -c Release -o /app/publish
# run app
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Example.Export.dll"]

I am starting the project and everything runs normally:
enter image description here
enter image description here

Edit 1: I am providing the Docker logs exactly after calling the await this.pdfRenderer.RenderHtmlAsPdfAsync method after which the project stops. (Note: I am including the last X lines, as the whole log is really big and doesn't hold an error)

13:47:16 (139776153876224): Found job 2 in group 1 (of 1 groups)
13:47:16 (139776153876224): Found job 2 in group 1 (of 1 groups)
13:47:16 (139776153876224): Printing from browser to '/tmp/pdfzwqWbJ'
13:47:16 (139776153876224): Printing from browser to '/tmp/pdfzwqWbJ'
13:47:16 (139776153876224): Received browser print callback for path '/tmp/pdfzwqWbJ' (1)
13:47:16 (139776153876224): Received browser print callback for path '/tmp/pdfzwqWbJ' (1)
13:47:16 (139776153876224): Print finished for browser 2(success: 1)
13:47:16 (139776153876224): Print finished for browser 2(success: 1)
13:47:16 (139776153876224): Resolving job for browser 2 with 80743 bytes
13:47:16 (139776153876224): Resolving job for browser 2 with 80743 bytes
13:47:16 (139776153876224): PdfDocumentFactory created document 0x7f201403a860 from 80743 bytes
13:47:16 (139776153876224): PdfDocumentFactory created document 0x7f201403a860 from 80743 bytes
13:47:16 (139776153876224): Resolving job for browser 2 with 1 page document
13:47:16 (139776153876224): Resolving job for browser 2 with 1 page document
13:47:16 (139776153876224): Generating bytes for document 0x7f201403a860
13:47:16 (139776153876224): Generating bytes for document 0x7f201403a860
13:47:16 (139776153876224): Successfully generated 80751 bytes for document 0x7f201403a860
13:47:16 (139776153876224): Successfully generated 80751 bytes for document 0x7f201403a860
13:47:16 (139776153876224): PdfDocumentFactory closed document 0x7f201403a860
13:47:16 (139776153876224): PdfDocumentFactory closed document 0x7f201403a860
13:47:16 (139776153876224): Closing browser 2
13:47:16 (139776153876224): Closing browser 2
13:47:16 (139776153876224): Destroying browser (id:2)
13:47:16 (139776153876224): Destroying browser (id:2)
13:47:16 (139776153876224): Finished job 2
13:47:16 (139776153876224): Finished job 2
13:47:16 (139776153876224): Found job 2 in group 1 (of 1 groups)
13:47:16 (139776153876224): Found job 2 in group 1 (of 1 groups)
13:47:16 (139776153876224): Job group 1 finished
13:47:16 (139776153876224): Job group 1 finished
13:47:16 (139776153876224): Job group 1 has overlays
13:47:16 (139776153876224): Job group 1 has overlays
13:47:16 (139776153876224): Retrieved 80751 bytes for job group 1 page 0 overlay 2
13:47:16 (139776153876224): Retrieved 80751 bytes for job group 1 page 0 overlay 2
13:47:16 (139776153876224): PdfDocumentFactory created document 0x7f201403a860 from 7745 bytes
13:47:16 (139776153876224): PdfDocumentFactory created document 0x7f201403a860 from 7745 bytes
13:47:16 (139776153876224): Applying overlay to page 0
13:47:16 (139776153876224): Applying overlay to page 0
13:47:16 (139776153876224): PdfDocumentFactory created document 0x7f202024d270 from 80751 bytes
13:47:16 (139776153876224): PdfDocumentFactory created document 0x7f202024d270 from 80751 bytes
13:47:16 (139776153876224): PdfDocumentFactory closed document 0x7f202024d270
13:47:16 (139776153876224): PdfDocumentFactory closed document 0x7f202024d270
13:47:16 (139776153876224): Generating bytes for document 0x7f201403a860
13:47:16 (139776153876224): Generating bytes for document 0x7f201403a860
13:47:16 (139776153876224): Successfully generated 88299 bytes for document 0x7f201403a860
13:47:16 (139776153876224): Successfully generated 88299 bytes for document 0x7f201403a860
13:47:16 (139776153876224): PdfDocumentFactory closed document 0x7f201403a860
13:47:16 (139776153876224): PdfDocumentFactory closed document 0x7f201403a860
13:47:16 (139776153876224): Successfully applied overlays
13:47:16 (139776153876224): Successfully applied overlays
13:47:16 (139776153876224): CefMessagePumpStd::Quit()
13:47:16 (139776892073728): PdfDocumentFactory closed document 0x7f2050020740
13:47:16 (139776153876224): CefMessagePumpStd::Quit()
13:47:16 (139776892073728): PdfDocumentFactory closed document 0x7f2050020740
13:47:16 (139776892073728): PdfDocumentFactory created document 0x7f2050020740 from 88299 bytes
13:47:16 (139776892073728): PdfDocumentFactory created document 0x7f2050020740 from 88299 bytes
13:47:16 (139776892073728): Storing updated document 0
13:47:16 (139776892073728): Storing updated document 0

Edit 1 - Temporary Solution

I was able to make a temporary solution to the problem as suggested in the comments by @ScottMildenberger. After changing the way I deploy to Azure it's working on production now.

Deploy to Azure App Service as Zip Deploy. The tricky part is that in the Configuration section in the App Service we have to change one application setting. Go to Application Settings and change WEBSITE_RUN_FROM_PACKAGE to have a value of 0. This gives the App Service read and write permissions. We do that because IronPdf is doing file operations behind the scenes and needs write access.
WEBSITE_RUN_FROM_PACKAGE or if you are using Azure pipelines with YML:

- task: AzureTask@4
  inputs:
    ... inputs ...
    appType: 'webApp'
    packageForLinux: 'path.zip'
    AppSettings: '-WEBSITE_RUN_FROM_PACKAGE 0'
    enableCustomDeployment: true
    DeploymentType: 'zipDeploy'
    TakeAppOfflineFlag: false

I am still not able to run it under the Docker Linux container. In case I fix it, I will edit again with the solution.

3

There are 3 best solutions below

0
On

I don't normally read all comments, asnswer was there in Scott Mildenberger comment.

If anyone facing issue with IronPdf.HtmlToPdf().RenderHtmlAsPdf(str) in Azure and using Azure Release Pipeline, check solution below:

enter image description here

0
On

I was having the same issue, we've figured out that it was heppning with long html fragments. I've solved it by adding more resources to the pod (In my case we've set 1Gi of memory, with a limit of 2Gi). However, with even bigger html fragments (5Gbs) the RenderHtmlAsPdfAsync method is never returning the pdf. By printing the html in the Edge browser, we got a document of 144 pages in a couple of minutes, so it is something inside IronPdf (2023.4.4) that is failing.

1
On

The solution appears to be to use Docker from the command line. When using Visual Studio (17.0.2) on MacOS built-in debugger docker-compose launch setting, I ran into your same problem. However, when using Docker from the command line, it did not run into the problem, and I was able to repeatedly call "RenderHtmlAsPdfAsync" over and over without the program stopping execution. So, I think it has to do with some interaction with the debugger attached within the docker container.

I had sent an email to IronPdf support, and they responded with the following, which hopefully helps:

We are aware of the issue described, and the following points may help to avoid (though not fix the situation):

  • Remove all debug break points
  • Run in release mode
  • Run Docker outside of Visual Studio (by Docker command-line)
  • Update Visual Studio