How to Use wkhtmltopdf in a Docker Container
Build a Docker image that runs wkhtmltopdf with compatible libraries and fonts, writes PDFs to persistent storage, and handles security and rendering limits.
Direct answer: Install a wkhtmltopdf package built for your container’s Linux distribution and CPU architecture, add its runtime libraries and font configuration, then run it against an HTML file or URL. Write the PDF to a mounted or application-managed output directory so it survives container exit. The converter runs headlessly; it does not need an X display.
wkhtmltopdf renders HTML to PDF using Qt WebKit. Container compatibility depends on more than the executable: libraries, fontconfig, fonts, and the build’s feature set all matter. The project describes its Qt/WebKit foundation as old, so consider the security and maintenance tradeoffs before adopting it for a new service.
1. Choose a compatible package
Start with the operating system and architecture of the image you will run. Use a package built for that distribution and architecture, and follow its installation instructions. Do not assume a Linux binary built for one environment will work in any other image.
- Check the C library: Alpine uses musl; many Linux packages expect glibc. A package intended for a glibc distribution may fail in Alpine.
- Install runtime dependencies: A build described as statically linked can still require system packages.
- Install font support and fonts: The renderer needs font configuration and fonts suitable for your documents. Add the fonts your output actually uses.
- Verify the build: Distribution builds can differ from patched-Qt builds. Check whether your binary supports features your documents need, including headers, footers, and multi-object PDFs.
The project download page documents distribution-specific packages and an Amazon Linux 2 container example. Treat that example as a pattern for that package, not a universal Dockerfile. Its example sets LD_LIBRARY_PATH=/opt/lib and FONTCONFIG_PATH=/opt/fonts; other packages may use different paths. See the wkhtmltopdf downloads and installation notes.
2. Install it in the image
There is no single official Dockerfile that fits every base image. The following template shows where to install a package and runtime dependencies. Replace the placeholders with the package source and dependencies documented for your selected distribution and architecture; do not build an image with these placeholder commands unchanged.
# Example structure: adapt package installation to your base distribution.
FROM your-linux-base:your-version
# Install the distribution- and architecture-matched wkhtmltopdf package,
# fontconfig, freetype, and the fonts your documents require.
# Use your distribution's package manager and the project's package guidance.
WORKDIR /work
COPY input.html /work/input.html
RUN mkdir -p /out
CMD ["wkhtmltopdf", "/work/input.html", "/out/output.pdf"]
For a production image, pin the base image and package version in your normal build process, keep the runtime dependencies in the final image, and avoid relying on files installed only in a build stage. If you bundle an extracted distribution-specific binary, include its libraries and font files and set the documented environment paths.
3. Run the container and persist the PDF
For a locally available HTML file, mount both the input and output paths. This example assumes the image is named html-to-pdf and its command accepts the paths shown above:
docker build -t html-to-pdf .
mkdir -p output
docker run --rm \
-v "$PWD/input.html:/work/input.html:ro" \
-v "$PWD/output:/out" \
html-to-pdf
The resulting file is output/output.pdf on the host. A container’s writable layer is usually temporary from the application’s perspective, so use a bind mount, a Docker volume, or an application storage step when the PDF must remain available.
You can also pass a URL instead of a filename:
docker run --rm \
-v "$PWD/output:/out" \
html-to-pdf \
wkhtmltopdf https://example.com /out/example.pdf
Ensure the container can resolve and reach the URL. If the page is private, supply credentials only through an appropriate secret mechanism and avoid putting sensitive values in image layers or shell history.
4. Use wkhtmltopdf’s command-line options correctly
The general syntax is wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>. Global options go before document objects. Objects can be pages, a cover, or a table of contents, in the order they should appear. Page-specific options belong with the relevant page object. Consult the official command-line usage reference for the options supported by your version.
# One page from a local file
wkhtmltopdf /work/input.html /out/output.pdf
# One page from a URL
wkhtmltopdf https://example.com /out/page.pdf
# Multiple objects: check that your build supports the needed features
wkhtmltopdf cover /work/cover.html page /work/chapter.html /out/book.pdf
Do not assume every option works identically across builds. In particular, verify the installed binary’s patched-Qt status before depending on multi-object documents, headers, or footers.
5. Check the binary and output
- Build the image and run
wkhtmltopdf --versioninside it. Record the version as part of deployment diagnostics. - Convert a small local HTML fixture using the fonts and options your actual documents need.
- Inspect the PDF for missing glyphs, unexpected page breaks, absent headers or footers, and blank content.
- Run the same conversion in the final runtime image, not just a larger development image.
The project’s downloads page identifies 0.12.6 as the stable series and dates that release to June 11, 2020. That is dated project information, not a guarantee that it is the right package for a current deployment. Check the current package listing and test your target distribution and architecture.
6. Security and operational limits
The project warns against using wkhtmltopdf with untrusted HTML or JavaScript unless it has been sanitized; its status page says this can lead to complete server takeover. Treat user-controlled markup, scripts, and resource references as a serious security boundary. Sanitize inputs and run conversion with least privilege and suitable isolation. The project suggests considering mandatory access controls such as AppArmor or SELinux.
For URL inputs, also decide which destinations the renderer may access. A conversion process that can fetch arbitrary URLs should not be given broad network access by default. Restrict its network and filesystem access to what the job needs, and keep credentials out of user-controlled documents.
wkhtmltopdf’s project status page describes its Qt/WebKit base as old, noting that Qt 4 is unsupported and the WebKit version has not been updated since 2012. Review whether that legacy rendering stack fits your security and maintenance requirements. The project suggests WeasyPrint or Prince for reports from HTML you control, and Puppeteer or a wrapper when pages depend on dynamic JavaScript. These are project recommendations, not a universal ranking.
7. Troubleshooting
| Symptom | Likely cause | What to check or fix |
|---|---|---|
not found or executable will not start |
Wrong package, CPU architecture, C library, or missing runtime library | Match the package to the image’s distribution and architecture. Check whether it expects glibc or musl and install the documented runtime dependencies. |
| Shared library error at startup | Required system libraries are absent or not on the runtime library path | Install the package’s required libraries in the final image. For a bundled binary, use the library path documented for that build. |
| Fonts are missing or glyphs look wrong | Fontconfig, freetype, or document fonts are missing or undiscoverable | Install font configuration and the required fonts. Set the package’s documented font paths and verify with a representative document. |
| PDF is blank or remote resources are absent | The container cannot reach the URL or fetch page resources, or the document is not ready when captured | Check DNS and outbound connectivity, resource URLs, and any authentication requirements. wkhtmltopdf uses its WebKit renderer; pages depending on modern or dynamic JavaScript may not render as expected. |
| Headers, footers, or multiple objects do not work | The installed binary’s build lacks the expected patched-Qt behavior | Check wkhtmltopdf --version and the package’s build details; choose a build that supports the required features and verify it in the container. |
| PDF disappears after the container exits | Output was written only into the container’s temporary writable layer | Mount a host directory or volume at the output path, or have the application persist the generated file. |
| Conversion fails on user-supplied content | Untrusted markup or scripts are being passed into a renderer with a serious security warning | Do not process it as-is. Sanitize and isolate the input, minimize process privileges, and restrict network and filesystem access. |
8. Performance, reliability, and cost
The researched project sources do not publish a relevant benchmark or reliability statistic, so size capacity from measurements on your own documents and target container. Measure representative conversions, including large pages, local fonts, and remote resources. Limit concurrency to what the container’s CPU and memory can sustain, and put a timeout around jobs so stalled URL loads do not occupy workers indefinitely.
For reliable output, write to a temporary file and publish or move it into its final location only after the converter exits successfully and the file is present. Capture standard error and the exit code for diagnosis. Keep the PDF outside the container’s ephemeral filesystem when it must outlive the job. Package updates and a repeatable rendering fixture help surface changes in fonts or distribution dependencies.
There is no per-conversion service price in the sources used here: self-hosting cost depends on the compute, storage, and operational work of your deployment. For dynamic pages, security-sensitive inputs, or hard-to-maintain package combinations, evaluate another renderer against your document requirements before committing.
Or skip the browser setup
If your goal is a screenshot rather than a PDF, ScreenshotNeo is a website screenshot API and MCP server. Its one-call API returns PNG, JPEG, WebP, or PDF output. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners, popups, and chat widgets are removed before the shot.
- Bot checks, blank pages, and failed loads are never billed.
- An MCP server lets AI agents take screenshots.
- 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
FAQ
Does wkhtmltopdf need X or a display server in Docker?
No. The project describes it as headless, so the upstream build does not require a display service.
Can I use the same Dockerfile on Alpine and Debian?
Do not assume so. Match the binary and dependencies to the image; Alpine’s musl environment differs from the glibc environment expected by many Linux packages.
Is wkhtmltopdf a good choice for a new renderer?
That depends on security requirements, page behavior, and required PDF features. Its project describes the Qt/WebKit foundation as old, so compare maintained alternatives against your workload.


