# How to Set Up IronPDF for Java on Azure
This guide covers everything needed to deploy [IronPDF for Java](https://ironpdf.com/java/) inside an Azure Functions container and generate PDFs on demand from a serverless HTTP endpoint. Because IronPDF ships a native Chromium rendering engine, it must be packaged as a Docker image; standard Zip deployment on Azure Functions cannot execute the binaries IronPDF relies on at runtime. Following this guide, a working Azure Function will accept a URL as a query parameter and return a fully rendered PDF as a downloadable file.
The approach uses the [Microsoft-recommended custom container workflow](https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-function-linux-custom-image) for Linux-based Azure Functions. A Maven project provides the function code and dependency management. Docker builds the container image, which is pushed to a registry and referenced by the Azure Function App. Once deployed, cold-start time is the main performance consideration; subsequent invocations are fast and consistent.
Before beginning, make sure the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli), Docker Desktop, Maven 3.8+, and JDK 11 or JDK 17 are installed locally. An active Azure subscription with permission to create Function Apps and storage accounts is also required.
*as-heading:2(Quickstart: Deploy IronPDF for Java on Azure Functions)*
The code below shows the complete `RenderPdf` Azure Function. It accepts a `url` query parameter and returns a PDF byte stream. Add this to `Function.java` after completing the Maven dependency setup in the sections that follow.
```java
import com.microsoft.azure.functions.*;
import com.ironsoftware.ironpdf.PdfDocument;
import java.util.Optional;
public class Function {
/**
* HTTP-triggered Azure Function: accepts a URL, renders it as a PDF,
* and returns the PDF bytes as a downloadable attachment.
*/
@FunctionName("RenderPdf")
public HttpResponseMessage renderPdf(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("RenderPdf function triggered.");
// Read the target URL from the query string
final String url = request.getQueryParameters().get("url");
if (url == null) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Provide a 'url' query parameter.")
.build();
}
try {
context.getLogger().info("Rendering URL as PDF: " + url);
// IronPDF renders the full page including JavaScript
PdfDocument pdf = PdfDocument.renderUrlAsPdf(url);
byte[] pdfBytes = pdf.getBinaryData();
return request.createResponseBuilder(HttpStatus.OK)
.body(pdfBytes)
.header("Content-Disposition", "attachment; filename=output.pdf")
.header("Content-Type", "application/pdf")
.build();
} catch (Exception ex) {
context.getLogger().severe("PDF rendering failed: " + ex.getMessage());
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body("PDF rendering failed. Check function logs for details.")
.build();
}
}
}
```
!!!--LIBRARY_START_TRIAL_BLOCK--!!!
*as-heading:2(Table of Contents)*
- [What Are the Prerequisites?](#prerequisites)
- [How Do You Set Up the Azure Function Project?](#set-up-project)
- [How Do You Add IronPDF Dependencies to Your Maven Project?](#add-ironpdf-dependencies)
- [How Do You Write the RenderPdf Function?](#write-renderpdf-function)
- [How Do You Configure the Dockerfile for IronPDF?](#configure-dockerfile)
- [How Do You Build and Push the Docker Image?](#build-push-docker)
- [How Do You Deploy the Function to Azure?](#deploy-to-azure)
- [How Do You Trigger and Test the Function?](#trigger-and-test)
- [What Are the Next Steps?](#next-steps)
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
## What Are the Prerequisites?
Before starting, confirm that all required tools are installed and an Azure subscription is active. Skipping these checks often results in build failures midway through the deployment process.
**Local tooling required:**
- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) (version 2.40 or later)
- [Docker Desktop](https://www.docker.com/products/docker-desktop/) with Linux containers enabled
- Maven 3.8 or later
- JDK 11 or JDK 17 (JDK 17 is the recommended LTS version)
- [Azure Functions Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local) v4
**Azure resources required:**
- An active Azure subscription
- Permissions to create Resource Groups, Storage Accounts, and Function App Plans
- A Docker Hub account (or Azure Container Registry) to host the built image
[[n:(IronPDF for Java requires the `ironpdf-engine-linux-x64` artifact when running inside any Docker container. Standard Zip deployment on Azure Functions cannot execute IronPDF's native binaries; Docker is the only supported deployment method.)]]
Run `az login` to authenticate the Azure CLI before proceeding to the next section.
## How Do You Set Up the Azure Function Project?
The Microsoft guide for [creating a function on Linux using a custom image](https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-function-linux-custom-image) covers the complete scaffolding process. Follow those steps with one important selection: choose **Java** when prompted for a programming language.
Work through the guide until the scaffolded project builds and the placeholder function runs locally using the Azure Functions Core Tools. Verify this with:
```bash
mvn clean package
func start
```
Once the placeholder responds to a local HTTP request, the project structure is correct and ready for IronPDF integration. The key files are `pom.xml` (Maven configuration), `Function.java` (function code), and `Dockerfile` (container definition).
[[i:(The Azure Functions Maven archetype generates a `host.json` and `local.settings.json` alongside `pom.xml`. The `local.settings.json` file stores environment variables for local development; it is excluded from source control by default and should never be committed.)]]
## How Do You Add IronPDF Dependencies to Your Maven Project?
IronPDF for Java is distributed through Maven Central. Two artifacts are required: the core `ironpdf` library that provides the Java API, and `ironpdf-engine-linux-x64` which bundles the native Chromium engine compiled for Linux x86-64. The engine artifact is what makes Docker deployment mandatory; it ships binaries that must be executed at runtime.
Open `pom.xml` and add the following inside the `<dependencies>` block. Replace `LATEST_VERSION` with the current release available on [Maven Central](https://central.sonatype.com/artifact/com.ironsoftware/ironpdf):
```xml
<dependencies>
<!-- IronPDF Java API -->
<dependency>
<groupId>com.ironsoftware</groupId>
<artifactId>ironpdf</artifactId>
<version>LATEST_VERSION</version>
</dependency>
<!--
Linux x64 engine — required for Docker/Azure Functions.
This artifact bundles the native Chromium renderer for Linux.
-->
<dependency>
<groupId>com.ironsoftware</groupId>
<artifactId>ironpdf-engine-linux-x64</artifactId>
<version>LATEST_VERSION</version>
</dependency>
</dependencies>
```
Both artifacts must use the same version number. Mismatched versions between `ironpdf` and `ironpdf-engine-linux-x64` cause a runtime exception when the function first attempts to render a PDF.
After updating `pom.xml`, run `mvn dependency:resolve` to verify that Maven can download both artifacts from Central before investing time in building the Docker image.
[[t:(Check the [IronPDF for Java release notes](https://ironpdf.com/java/product-updates/changelog/) for the latest stable version. Using the most recent release ensures compatibility with the latest Chromium rendering engine and avoids known bugs.)]]
## How Do You Write the RenderPdf Function?
The `RenderPdf` function is an HTTP-triggered Azure Function that accepts a `url` query parameter, renders the target page using IronPDF's Chromium-based engine, and returns the resulting PDF as a binary response with a `Content-Disposition: attachment` header. This header tells the browser (or HTTP client) to download the PDF rather than display it inline.
The complete function code is shown in the Quickstart above. Place it in `src/main/java/com/example/Function.java`, replacing or extending the placeholder generated by the Maven archetype.
```java
import com.microsoft.azure.functions.*;
import com.ironsoftware.ironpdf.PdfDocument;
import java.util.Optional;
public class Function {
@FunctionName("RenderPdf")
public HttpResponseMessage renderPdf(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
// Log each invocation for Azure Monitor / Application Insights
context.getLogger().info("RenderPdf triggered.");
final String url = request.getQueryParameters().get("url");
// Return 400 if no URL was supplied
if (url == null) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Provide a 'url' query parameter.")
.build();
}
try {
// renderUrlAsPdf launches Chromium, loads the page, and captures it as PDF
PdfDocument pdf = PdfDocument.renderUrlAsPdf(url);
// getBinaryData returns the raw PDF bytes ready for transmission
byte[] pdfBytes = pdf.getBinaryData();
return request.createResponseBuilder(HttpStatus.OK)
.body(pdfBytes)
.header("Content-Disposition", "attachment; filename=output.pdf")
.header("Content-Type", "application/pdf")
.build();
} catch (Exception ex) {
context.getLogger().severe("Rendering error: " + ex.getMessage());
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body("PDF rendering failed.")
.build();
}
}
}
```
`PdfDocument.renderUrlAsPdf(url)` launches a headless Chromium instance inside the container, fully loads the target URL (including JavaScript), and captures the rendered output as a PDF. This produces output that is visually identical to what a user sees in a browser, making it suitable for capturing modern web applications, dashboards, and report pages.
[[n:(The `authLevel = AuthorizationLevel.ANONYMOUS` setting in the function trigger makes the endpoint publicly accessible. For production deployments, change this to `FUNCTION` or `ADMIN` and pass the function key in the request header.)]]
## How Do You Configure the Dockerfile for IronPDF?
IronPDF's Chromium engine depends on a set of shared Linux libraries that are not included in the base Azure Functions image. The base image `mcr.microsoft.com/azure-functions/java:4-java17-build` is built on Debian 11, so the packages must be installed using `apt`.
The following `RUN` commands must be added to the `Dockerfile` generated by the Azure Functions Maven archetype. Place them after the `FROM` instruction and before the `COPY` steps that add the application JAR:
```dockerfile
FROM mcr.microsoft.com/azure-functions/java:4-java17-build AS installer-env
# Install system dependencies required by IronPDF's Chromium renderer
RUN apt-get update && apt-get 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 \
&& apt-get install -y xvfb libva-dev libgdiplus \
&& rm -rf /var/lib/apt/lists/*
# Copy the built function JAR
COPY --from=installer-env /home/site/wwwroot /home/site/wwwroot
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
```
The `libgdiplus` package provides GDI+ compatibility for graphics rendering. `libnss3` and `libatk-bridge2.0-0` are required by Chromium's sandboxing and accessibility layers. `xvfb` provides a virtual framebuffer, which Chromium requires even in headless mode on some Debian configurations. The `rm -rf /var/lib/apt/lists/*` step at the end of the `RUN` block removes the package manager cache, keeping the final image size as small as possible.
[[i:(If the Azure Functions base image version changes or a different Linux distro is used as the base, the required packages may differ. Consult the [IronPDF Linux Installation Guide](/get-started/linux/) for a complete dependency matrix across Debian, Ubuntu, CentOS, and Alpine.)]]
## How Do You Build and Push the Docker Image?
With the Maven project built and the Dockerfile updated, the container image can be assembled and uploaded to a Docker registry. Azure Functions pulls this image when the Function App is created or updated.
**Step 1: Build and package the Maven project**:
```bash
# Compile the Java code and package it as a JAR
mvn clean package
```
Maven compiles the function code, resolves all dependencies (including both IronPDF artifacts), and produces a deployable JAR in the `target/` directory. Fix any compilation errors before proceeding.
**Step 2: Build the Docker image**:
```bash
# Replace <DOCKER_ID> with your Docker Hub username or ACR login server
docker build --tag <DOCKER_ID>/ironpdf-azure-functions:v1.0.0 .
```
The build installs the Linux packages listed in the Dockerfile, copies the JAR, and layers everything into a final image. On first build this may take several minutes as package downloads and layer caching are established. Subsequent builds using the same base image are significantly faster.
**Step 3: Push the image to Docker Hub**:
```bash
# Authenticate if not already logged in
docker login
# Push the image to the registry
docker push <DOCKER_ID>/ironpdf-azure-functions:v1.0.0
```
[[t:(Azure Container Registry (ACR) is a private alternative to Docker Hub. ACR integrates directly with Azure Active Directory and is the recommended choice for production workloads where image privacy is important.)]]
## How Do You Deploy the Function to Azure?
With the image in the registry, the Azure Function App can be created (or updated) to reference it. The `az functionapp create` command provisions the Function App, links it to a storage account, and sets the container image in a single step.
**Step 1: Create or update the Function App**:
```bash
az functionapp create \
--name <APP_NAME> \
--storage-account <STORAGE_NAME> \
--resource-group AzureFunctionsContainers-rg \
--plan myPremiumPlan \
--deployment-container-image-name <DOCKER_ID>/ironpdf-azure-functions:v1.0.0
```
Replace `<APP_NAME>` with a globally unique name for the Function App, `<STORAGE_NAME>` with an existing Azure Storage account name, and `<DOCKER_ID>` with the Docker Hub username or ACR login server used in the previous step.
The `--plan myPremiumPlan` flag selects a Premium hosting plan. IronPDF's Chromium engine consumes significant memory during rendering; the Consumption plan's 1.5 GB memory ceiling is often insufficient. The Premium plan provides at least 3.5 GB and supports pre-warmed instances that eliminate cold-start latency.
**Step 2: Verify the deployment**:
```bash
# Check that the function app is running and the container has been pulled
az functionapp show \
--name <APP_NAME> \
--resource-group AzureFunctionsContainers-rg \
--query "state"
```
The command returns `"Running"` when the container has started successfully. If it returns `"Starting"` or an error, check the Azure portal's Log Stream under the Function App for container pull or startup errors.
[[w:(The Consumption (Serverless) plan is not recommended for IronPDF on Azure Functions. PDF rendering with Chromium requires more memory than the Consumption plan allocates. Use a Premium or Dedicated (App Service) plan to avoid out-of-memory errors.)]]
## How Do You Trigger and Test the Function?
Once the Function App reports a `Running` state, the `RenderPdf` endpoint is ready to accept requests. The endpoint URL follows a predictable pattern based on the Function App name and the function name defined in the `@FunctionName` annotation.
**Test using a browser or curl:**
```bash
# Replace <APP_NAME> with the Function App name
curl -o output.pdf \
"https://<APP_NAME>.azurewebsites.net/api/RenderPdf?url=https://www.example.com"
```
A successful response saves a PDF file named `output.pdf` to the current directory. The `-o` flag in curl writes the binary response body to a file rather than printing it to the terminal.
When testing in a browser, navigate to:
`https://<APP_NAME>.azurewebsites.net/api/RenderPdf?url=https://www.example.com`
The browser will prompt to download a PDF. Open it to verify the page was rendered correctly.
[[n:(The first request after a cold start may take 20-60 seconds as Azure pulls the container image and IronPDF initializes Chromium. Subsequent requests within the same container lifetime are much faster. The Premium plan's pre-warmed instance feature eliminates cold starts by keeping at least one instance running continuously.)]]
**Checking logs for errors:** Navigate to the Azure portal, open the Function App, and select **Log Stream** under **Monitoring**. Log entries from `context.getLogger()` calls appear here in near-real time, which makes diagnosing rendering failures straightforward.
## What Are the Next Steps?
This guide demonstrated how to deploy IronPDF for Java inside an Azure Functions Docker container, write an HTTP-triggered function that renders URLs as PDFs, configure the Dockerfile with the required Linux dependencies, and test the live endpoint. The same pattern extends to more advanced use cases with minimal changes.
**Extend the function:**
- Render HTML strings directly using `PdfDocument.renderHtmlAsPdf(htmlString)` instead of a URL
- Apply watermarks, merge multiple PDFs, or add digital signatures using [IronPDF's full Java PDF API](https://ironpdf.com/java/object-reference/api/)
- Read request headers or POST body to pass custom HTML content or rendering options
**Improve production readiness:**
- Switch `authLevel` to `FUNCTION` and rotate function keys regularly
- Use [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview) to store any secrets referenced in application settings
- Configure [Application Insights](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview) for end-to-end observability of rendering latency and failure rates
- Set up a [Docker image update webhook](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tutorial-deploy-update) so Azure automatically redeploys when a new image version is pushed
**Explore more IronPDF for Java guides:**
- [IronPDF for Java: Linux Installation Guide](/get-started/linux/)
- [Generate PDFs from HTML in Java](/java/tutorials/html-to-pdf/)
- [IronPDF for Java: Docker Deployment Guide](/java/get-started/use-ironpdfengine/)
- [Full IronPDF Java API Reference](https://ironpdf.com/java/object-reference/api/)
[Start a free IronPDF trial](#trial-license) to access all rendering and manipulation features without a watermark during the evaluation period. When ready to deploy to production, [view IronPDF licensing options](#licensing) to find the plan that fits the project scale.
This guide covers everything needed to deploy IronPDF for Java inside an Azure Functions container and generate PDFs on demand from a serverless HTTP endpoint. Because IronPDF ships a native Chromium rendering engine, it must be packaged as a Docker image; standard Zip deployment on Azure Functions cannot execute the binaries IronPDF relies on at runtime. Following this guide, a working Azure Function will accept a URL as a query parameter and return a fully rendered PDF as a downloadable file.
The approach uses the Microsoft-recommended custom container workflow for Linux-based Azure Functions. A Maven project provides the function code and dependency management. Docker builds the container image, which is pushed to a registry and referenced by the Azure Function App. Once deployed, cold-start time is the main performance consideration; subsequent invocations are fast and consistent.
Before beginning, make sure the Azure CLI, Docker Desktop, Maven 3.8+, and JDK 11 or JDK 17 are installed locally. An active Azure subscription with permission to create Function Apps and storage accounts is also required.
Quickstart: Deploy IronPDF for Java on Azure Functions
The code below shows the complete RenderPdf Azure Function. It accepts a url query parameter and returns a PDF byte stream. Add this to Function.java after completing the Maven dependency setup in the sections that follow.
import com.microsoft.azure.functions.*;import com.ironsoftware.ironpdf.PdfDocument;import java.util.Optional;public class Function { /** * HTTP-triggered Azure Function: accepts a URL, renders it as a PDF, * and returns the PDF bytes as a downloadable attachment. */ @FunctionName("RenderPdf") public HttpResponseMessage renderPdf( @HttpTrigger( name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request, final ExecutionContext context) { context.getLogger().info("RenderPdf function triggered."); // Read the target URL from the query string final String url = request.getQueryParameters().get("url"); if (url == null) { return request.createResponseBuilder(HttpStatus.BAD_REQUEST) .body("Provide a 'url' query parameter.") .build(); } try { context.getLogger().info("Rendering URL as PDF: " + url); // IronPDF renders the full page including JavaScript PdfDocument pdf = PdfDocument.renderUrlAsPdf(url); byte[] pdfBytes = pdf.getBinaryData(); return request.createResponseBuilder(HttpStatus.OK) .body(pdfBytes) .header("Content-Disposition", "attachment; filename=output.pdf") .header("Content-Type", "application/pdf") .build(); } catch (Exception ex) { context.getLogger().severe("PDF rendering failed: " + ex.getMessage()); return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR) .body("PDF rendering failed. Check function logs for details.") .build(); } }}
import com.microsoft.azure.functions.*;
import com.ironsoftware.ironpdf.PdfDocument;
import java.util.Optional;
public class Function {
/**
* HTTP-triggered Azure Function: accepts a URL, renders it as a PDF,
* and returns the PDF bytes as a downloadable attachment.
*/
@FunctionName("RenderPdf")
public HttpResponseMessage renderPdf(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("RenderPdf function triggered.");
// Read the target URL from the query string
final String url = request.getQueryParameters().get("url");
if (url == null) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Provide a 'url' query parameter.")
.build();
}
try {
context.getLogger().info("Rendering URL as PDF: " + url);
// IronPDF renders the full page including JavaScript
PdfDocument pdf = PdfDocument.renderUrlAsPdf(url);
byte[] pdfBytes = pdf.getBinaryData();
return request.createResponseBuilder(HttpStatus.OK)
.body(pdfBytes)
.header("Content-Disposition", "attachment; filename=output.pdf")
.header("Content-Type", "application/pdf")
.build();
} catch (Exception ex) {
context.getLogger().severe("PDF rendering failed: " + ex.getMessage());
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body("PDF rendering failed. Check function logs for details.")
.build();
}
}
}
Java
Start using IronPDF in your project today with a free trial.
Before starting, confirm that all required tools are installed and an Azure subscription is active. Skipping these checks often results in build failures midway through the deployment process.
Permissions to create Resource Groups, Storage Accounts, and Function App Plans
A Docker Hub account (or Azure Container Registry) to host the built image
Important: IronPDF for Java requires the ironpdf-engine-linux-x64 artifact when running inside any Docker container. Standard Zip deployment on Azure Functions cannot execute IronPDF's native binaries; Docker is the only supported deployment method.
Run az login to authenticate the Azure CLI before proceeding to the next section.
How Do You Set Up the Azure Function Project?
The Microsoft guide for creating a function on Linux using a custom image covers the complete scaffolding process. Follow those steps with one important selection: choose Java when prompted for a programming language.
Work through the guide until the scaffolded project builds and the placeholder function runs locally using the Azure Functions Core Tools. Verify this with:
mvn clean packagefunc start
mvn clean package
func start
SHELL
Once the placeholder responds to a local HTTP request, the project structure is correct and ready for IronPDF integration. The key files are pom.xml (Maven configuration), Function.java (function code), and Dockerfile (container definition).
Please note: The Azure Functions Maven archetype generates a host.json and local.settings.json alongside pom.xml. The local.settings.json file stores environment variables for local development; it is excluded from source control by default and should never be committed.
How Do You Add IronPDF Dependencies to Your Maven Project?
IronPDF for Java is distributed through Maven Central. Two artifacts are required: the core ironpdf library that provides the Java API, and ironpdf-engine-linux-x64 which bundles the native Chromium engine compiled for Linux x86-64. The engine artifact is what makes Docker deployment mandatory; it ships binaries that must be executed at runtime.
Open pom.xml and add the following inside the <dependencies> block. Replace LATEST_VERSION with the current release available on Maven Central:
<dependencies> <!-- IronPDF Java API --> <dependency> <groupId>com.ironsoftware</groupId> <artifactId>ironpdf</artifactId> <version>LATEST_VERSION</version> </dependency> <!-- Linux x64 engine — required for Docker/Azure Functions. This artifact bundles the native Chromium renderer for Linux. --> <dependency> <groupId>com.ironsoftware</groupId> <artifactId>ironpdf-engine-linux-x64</artifactId> <version>LATEST_VERSION</version> </dependency></dependencies>
<dependencies>
<!-- IronPDF Java API -->
<dependency>
<groupId>com.ironsoftware</groupId>
<artifactId>ironpdf</artifactId>
<version>LATEST_VERSION</version>
</dependency>
<!--
Linux x64 engine — required for Docker/Azure Functions.
This artifact bundles the native Chromium renderer for Linux.
-->
<dependency>
<groupId>com.ironsoftware</groupId>
<artifactId>ironpdf-engine-linux-x64</artifactId>
<version>LATEST_VERSION</version>
</dependency>
</dependencies>
XML
Both artifacts must use the same version number. Mismatched versions between ironpdf and ironpdf-engine-linux-x64 cause a runtime exception when the function first attempts to render a PDF.
After updating pom.xml, run mvn dependency:resolve to verify that Maven can download both artifacts from Central before investing time in building the Docker image.
Tips: Check the IronPDF for Java release notes for the latest stable version. Using the most recent release ensures compatibility with the latest Chromium rendering engine and avoids known bugs.
How Do You Write the RenderPdf Function?
The RenderPdf function is an HTTP-triggered Azure Function that accepts a url query parameter, renders the target page using IronPDF's Chromium-based engine, and returns the resulting PDF as a binary response with a Content-Disposition: attachment header. This header tells the browser (or HTTP client) to download the PDF rather than display it inline.
The complete function code is shown in the Quickstart above. Place it in src/main/java/com/example/Function.java, replacing or extending the placeholder generated by the Maven archetype.
import com.microsoft.azure.functions.*;import com.ironsoftware.ironpdf.PdfDocument;import java.util.Optional;public class Function { @FunctionName("RenderPdf") public HttpResponseMessage renderPdf( @HttpTrigger( name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request, final ExecutionContext context) { // Log each invocation for Azure Monitor / Application Insights context.getLogger().info("RenderPdf triggered."); final String url = request.getQueryParameters().get("url"); // Return 400 if no URL was supplied if (url == null) { return request.createResponseBuilder(HttpStatus.BAD_REQUEST) .body("Provide a 'url' query parameter.") .build(); } try { // renderUrlAsPdf launches Chromium, loads the page, and captures it as PDF PdfDocument pdf = PdfDocument.renderUrlAsPdf(url); // getBinaryData returns the raw PDF bytes ready for transmission byte[] pdfBytes = pdf.getBinaryData(); return request.createResponseBuilder(HttpStatus.OK) .body(pdfBytes) .header("Content-Disposition", "attachment; filename=output.pdf") .header("Content-Type", "application/pdf") .build(); } catch (Exception ex) { context.getLogger().severe("Rendering error: " + ex.getMessage()); return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR) .body("PDF rendering failed.") .build(); } }}
import com.microsoft.azure.functions.*;
import com.ironsoftware.ironpdf.PdfDocument;
import java.util.Optional;
public class Function {
@FunctionName("RenderPdf")
public HttpResponseMessage renderPdf(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
// Log each invocation for Azure Monitor / Application Insights
context.getLogger().info("RenderPdf triggered.");
final String url = request.getQueryParameters().get("url");
// Return 400 if no URL was supplied
if (url == null) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Provide a 'url' query parameter.")
.build();
}
try {
// renderUrlAsPdf launches Chromium, loads the page, and captures it as PDF
PdfDocument pdf = PdfDocument.renderUrlAsPdf(url);
// getBinaryData returns the raw PDF bytes ready for transmission
byte[] pdfBytes = pdf.getBinaryData();
return request.createResponseBuilder(HttpStatus.OK)
.body(pdfBytes)
.header("Content-Disposition", "attachment; filename=output.pdf")
.header("Content-Type", "application/pdf")
.build();
} catch (Exception ex) {
context.getLogger().severe("Rendering error: " + ex.getMessage());
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body("PDF rendering failed.")
.build();
}
}
}
Java
PdfDocument.renderUrlAsPdf(url) launches a headless Chromium instance inside the container, fully loads the target URL (including JavaScript), and captures the rendered output as a PDF. This produces output that is visually identical to what a user sees in a browser, making it suitable for capturing modern web applications, dashboards, and report pages.
Important: The authLevel = AuthorizationLevel.ANONYMOUS setting in the function trigger makes the endpoint publicly accessible. For production deployments, change this to FUNCTION or ADMIN and pass the function key in the request header.
How Do You Configure the Dockerfile for IronPDF?
IronPDF's Chromium engine depends on a set of shared Linux libraries that are not included in the base Azure Functions image. The base image mcr.microsoft.com/azure-functions/java:4-java17-build is built on Debian 11, so the packages must be installed using apt.
The following RUN commands must be added to the Dockerfile generated by the Azure Functions Maven archetype. Place them after the FROM instruction and before the COPY steps that add the application JAR:
FROM mcr.microsoft.com/azure-functions/java:4-java17-build AS installer-env
# Install system dependencies required by IronPDF's Chromium renderer
RUN apt-get update && apt-get 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 \
&& apt-get install -y xvfb libva-dev libgdiplus \
&& rm -rf /var/lib/apt/lists/*
# Copy the built function JAR
COPY --from=installer-env /home/site/wwwroot /home/site/wwwroot
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
Text
The libgdiplus package provides GDI+ compatibility for graphics rendering. libnss3 and libatk-bridge2.0-0 are required by Chromium's sandboxing and accessibility layers. xvfb provides a virtual framebuffer, which Chromium requires even in headless mode on some Debian configurations. The rm -rf /var/lib/apt/lists/* step at the end of the RUN block removes the package manager cache, keeping the final image size as small as possible.
Please note: If the Azure Functions base image version changes or a different Linux distro is used as the base, the required packages may differ. Consult the IronPDF Linux Installation Guide for a complete dependency matrix across Debian, Ubuntu, CentOS, and Alpine.
How Do You Build and Push the Docker Image?
With the Maven project built and the Dockerfile updated, the container image can be assembled and uploaded to a Docker registry. Azure Functions pulls this image when the Function App is created or updated.
Step 1: Build and package the Maven project:
# Compile the Java code and package it as a JARmvn clean package
# Compile the Java code and package it as a JAR
mvn clean package
SHELL
Maven compiles the function code, resolves all dependencies (including both IronPDF artifacts), and produces a deployable JAR in the target/ directory. Fix any compilation errors before proceeding.
Step 2: Build the Docker image:
# Replace <DOCKER_ID> with your Docker Hub username or ACR login serverdocker build --tag <DOCKER_ID>/ironpdf-azure-functions:v1.0.0 .
# Replace <DOCKER_ID> with your Docker Hub username or ACR login server
docker build --tag <DOCKER_ID>/ironpdf-azure-functions:v1.0.0 .
SHELL
The build installs the Linux packages listed in the Dockerfile, copies the JAR, and layers everything into a final image. On first build this may take several minutes as package downloads and layer caching are established. Subsequent builds using the same base image are significantly faster.
Step 3: Push the image to Docker Hub:
# Authenticate if not already logged indocker login# Push the image to the registrydocker push <DOCKER_ID>/ironpdf-azure-functions:v1.0.0
# Authenticate if not already logged in
docker login
# Push the image to the registry
docker push <DOCKER_ID>/ironpdf-azure-functions:v1.0.0
SHELL
Tips: Azure Container Registry (ACR) is a private alternative to Docker Hub. ACR integrates directly with Azure Active Directory and is the recommended choice for production workloads where image privacy is important.
How Do You Deploy the Function to Azure?
With the image in the registry, the Azure Function App can be created (or updated) to reference it. The az functionapp create command provisions the Function App, links it to a storage account, and sets the container image in a single step.
Replace <APP_NAME> with a globally unique name for the Function App, <STORAGE_NAME> with an existing Azure Storage account name, and <DOCKER_ID> with the Docker Hub username or ACR login server used in the previous step.
The --plan myPremiumPlan flag selects a Premium hosting plan. IronPDF's Chromium engine consumes significant memory during rendering; the Consumption plan's 1.5 GB memory ceiling is often insufficient. The Premium plan provides at least 3.5 GB and supports pre-warmed instances that eliminate cold-start latency.
Step 2: Verify the deployment:
# Check that the function app is running and the container has been pulledaz functionapp show \ --name <APP_NAME> \ --resource-group AzureFunctionsContainers-rg \ --query "state"
# Check that the function app is running and the container has been pulled
az functionapp show \
--name <APP_NAME> \
--resource-group AzureFunctionsContainers-rg \
--query "state"
SHELL
The command returns "Running" when the container has started successfully. If it returns "Starting" or an error, check the Azure portal's Log Stream under the Function App for container pull or startup errors.
Warning: The Consumption (Serverless) plan is not recommended for IronPDF on Azure Functions. PDF rendering with Chromium requires more memory than the Consumption plan allocates. Use a Premium or Dedicated (App Service) plan to avoid out-of-memory errors.
How Do You Trigger and Test the Function?
Once the Function App reports a Running state, the RenderPdf endpoint is ready to accept requests. The endpoint URL follows a predictable pattern based on the Function App name and the function name defined in the @FunctionName annotation.
Test using a browser or curl:
# Replace <APP_NAME> with the Function App namecurl -o output.pdf \ "https://<APP_NAME>.azurewebsites.net/api/RenderPdf?url=https://www.example.com"
# Replace <APP_NAME> with the Function App name
curl -o output.pdf \
"https://<APP_NAME>.azurewebsites.net/api/RenderPdf?url=https://www.example.com"
SHELL
A successful response saves a PDF file named output.pdf to the current directory. The -o flag in curl writes the binary response body to a file rather than printing it to the terminal.
The browser will prompt to download a PDF. Open it to verify the page was rendered correctly.
Important: The first request after a cold start may take 20-60 seconds as Azure pulls the container image and IronPDF initializes Chromium. Subsequent requests within the same container lifetime are much faster. The Premium plan's pre-warmed instance feature eliminates cold starts by keeping at least one instance running continuously.
Checking logs for errors: Navigate to the Azure portal, open the Function App, and select Log Stream under Monitoring. Log entries from context.getLogger() calls appear here in near-real time, which makes diagnosing rendering failures straightforward.
What Are the Next Steps?
This guide demonstrated how to deploy IronPDF for Java inside an Azure Functions Docker container, write an HTTP-triggered function that renders URLs as PDFs, configure the Dockerfile with the required Linux dependencies, and test the live endpoint. The same pattern extends to more advanced use cases with minimal changes.
Extend the function:
Render HTML strings directly using PdfDocument.renderHtmlAsPdf(htmlString) instead of a URL
Start a free IronPDF trial to access all rendering and manipulation features without a watermark during the evaluation period. When ready to deploy to production, view IronPDF licensing options to find the plan that fits the project scale.
Frequently Asked Questions
Why is Docker necessary for deploying IronPDF on Azure Functions?
Docker is necessary because IronPDF includes a native Chromium rendering engine that requires specific shared Linux libraries. Standard Zip deployment on Azure Functions cannot execute these binaries, making Docker the only supported deployment method.
How do I configure Maven to work with IronPDF for Java?
To configure Maven for IronPDF, add the core IronPDF library and the ironpdf-engine-linux-x64 artifact in your pom.xml under the block. These are available on Maven Central and must match in version for compatibility.
What are the key dependencies needed for IronPDF's Chromium renderer?
Key dependencies required for IronPDF's Chromium renderer include libgdiplus, libnss3, libatk-bridge2.0-0, and several others. These ensure that Chromium can render content properly within a Debian-based container.
How can I test the RenderPdf function once deployed?
You can test the RenderPdf function using a browser or curl command by accessing the Azure Function's endpoint with a specific URL parameter. For instance, using curl, you can run `curl -o output.pdf "https://.azurewebsites.net/api/RenderPdf?url=https://www.example.com"` to download a PDF.
What Azure plan is recommended for running IronPDF, and why?
A Premium hosting plan is recommended for running IronPDF as it provides sufficient memory for the Chromium engine, which consumes significant resources. The Consumption plan's memory is often too limited for this purpose.
How can Docker image updates be automated for Azure Functions?
You can automate Docker image updates for Azure Functions by setting up a Docker image update webhook. This triggers Azure to redeploy the function when a new image version is pushed to your Docker registry.
What performance considerations exist when using IronPDF on Azure Functions?
Cold-start times can be significant due to container image loading and Chromium initialization. Using a Premium plan with pre-warmed instances can help mitigate cold-start delays, leading to more consistent invocation times.
Can IronPDF handle JavaScript-heavy web pages?
Yes, IronPDF uses a full Chromium-based rendering engine, which means it can load and render JavaScript-heavy web pages much like a browser would.
Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.