Linux + Docker Deployment
The SecureExchanges.Signature.NetCore SDK uses headless Chromium (via PuppeteerSharp) to certify PDFs. On Linux hosts, Chromium needs specific system libraries and a reproducible layout. This page documents the Dockerfile and apt dependencies required to run the SDK inside a Linux container.
This setup is reusable on any Linux container host: Azure Functions, Azure Container Apps, Azure App Service (Linux), Kubernetes, etc.
Prerequisites
- A .NET 8+ project that references
SecureExchanges.Signature.NetCore - Docker Desktop or a cloud builder (e.g.
az acr build) - A Chrome for Testing version aligned with the PuppeteerSharp version pulled by the SDK
Dockerfile
Multi-stage build. Stage 1 compiles the .NET project. Stage 2 installs the Chromium runtime dependencies, downloads Chrome for Testing, and copies the compiled output.
Note
The Dockerfile below targets Azure Functions (it uses the Functions base image and sets Functions-specific environment variables). It can also be run locally with docker build + docker run for testing.
For other hosts (Container Apps, App Service, Kubernetes), replace the runtime base image with mcr.microsoft.com/dotnet/aspnet:8.0 (or equivalent) and adjust the entrypoint accordingly.
Tip
A working sample is available on GitHub: AzureFunctionsSignature.netCore.
# Azure Functions .NET 8 Isolated Worker with headless Chromium.
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["AzureFunctionsSignature.netCore.csproj", "./"]
RUN dotnet restore "AzureFunctionsSignature.netCore.csproj"
COPY . .
RUN dotnet publish "AzureFunctionsSignature.netCore.csproj" \
-c Release \
-o /app/publish \
--no-restore \
/p:UseAppHost=false
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0 AS runtime
# Chromium runtime dependencies for Debian bookworm.
# If a future Chrome version crashes with "error while loading shared libraries: libXXX.so",
# add the lib here and rebuild.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
fonts-liberation \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libdrm2 \
libexpat1 \
libfontconfig1 \
libgbm1 \
libglib2.0-0 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxi6 \
libxkbcommon0 \
libxrandr2 \
libxrender1 \
libxshmfence1 \
libxss1 \
libxtst6 \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Chrome for Testing — version must match the one bundled with PuppeteerSharp.
# Check available versions: https://googlechromelabs.github.io/chrome-for-testing/
ARG CHROME_VERSION=146.0.7680.153
RUN wget -q "https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/chrome-linux64.zip" \
-O /tmp/chrome.zip \
&& mkdir -p /home/site/wwwroot/chromium \
&& unzip -q /tmp/chrome.zip -d /home/site/wwwroot/chromium \
&& chmod +x /home/site/wwwroot/chromium/chrome-linux64/chrome \
&& rm /tmp/chrome.zip
# Chromium is already present in the image — block PuppeteerSharp from re-downloading it at runtime.
# One worker per instance = one Chromium process shared = lower RAM footprint.
ENV SE_DISABLE_AUTO_DOWNLOAD=1 \
FUNCTIONS_WORKER_PROCESS_COUNT=1
COPY --from=build /app/publish /home/site/wwwroot
Required system libraries
Chromium does not ship with its own dependencies; they must be provided by the host. The apt-get install list above covers the libraries Chromium needs to start on Debian bookworm.
If a future Chromium build fails with error while loading shared libraries: libXXX.so: cannot open shared object file, add the missing package to the apt-get install list and rebuild.
Chrome for Testing version
PuppeteerSharp ships with an expected Chrome for Testing version. The image must install that exact version (or a compatible close one). The table below tracks the Chrome version required by each SDK release:
SecureExchanges.Signature.NetCore version |
Chrome for Testing version |
|---|---|
| 26.4.23.1 and later | 146.0.7680.153 |
If you use a newer SDK version not listed here:
- Identify the version PuppeteerSharp expects (at runtime, Puppeteer downloads into
/tmp/Chrome/Linux-<version>/). - Pick a matching build from the Chrome for Testing dashboard.
- Set the
CHROME_VERSIONbuild arg in the Dockerfile.
A version drift between the installed binary and PuppeteerSharp's expectations can cause launch failures or subtle rendering differences.
Environment variables
| Variable | Purpose |
|---|---|
SE_PUPPETEER_EXECUTABLE_PATH |
Absolute path to a Chromium binary. Overrides all other resolution steps. |
SE_DISABLE_AUTO_DOWNLOAD |
Set to 1 or true to prevent PuppeteerSharp from downloading Chromium at runtime. Recommended when the image already ships Chromium (as in the Dockerfile above). |
Note:
FUNCTIONS_WORKER_PROCESS_COUNTis specific to Azure Functions and is covered in Azure Functions Deployment.
Next steps
- For Azure Functions specifically — ACR, managed identity, linking the image to a Function App — see Azure Functions Deployment.
- For the SDK usage itself, see PDF Certification.
- For a full working sample project, see AzureFunctionsSignature.netCore on GitHub.