I’m working on a React application that displays customer records and I need to generate PDFs using headless Chrome via Puppeteer. My setup involves Docker containers for deployment.
My architecture includes:
- Frontend application container
- PDF generation service container
When I try to capture webpage content with Puppeteer and convert it to PDF, the resulting document is empty. The application logs show that API calls to fetch data aren’t being executed properly.
The page contains dynamic content since it’s a single page application with multiple data tables rendered using conditional rendering.
I’ve set up Puppeteer in Docker by manually installing Chrome dependencies since they don’t come pre-installed.
Here’s my PDF generation code:
const chromeBrowser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
});
const webPage = await chromeBrowser.newPage();
await webPage.goto(targetURL, { waitUntil: 'networkidle0' });
await webPage.waitFor(8000);
const elementHandle = await webPage.evaluateHandle(() => document.body);
const contentHandle = await webPage.evaluateHandle(element => element.innerHTML, elementHandle);
await elementHandle.dispose();
await contentHandle.dispose();
await webPage.pdf({ path: path.join(__dirname, './output.pdf') });
await chromeBrowser.close();
The frontend component structure looks like:
<div class="records">
<RecordItem v-for="record in customerRecords"
:key="record.uuid"
:data="record.details"/>
</div>
The customerRecords array gets populated via API calls but this data isn’t appearing in the generated PDF.
This works perfectly on my local machine but fails when running inside Docker containers.
Had this exact issue deploying a similar setup last year. Your PDF service container probably can’t reach your frontend container or the API endpoints that populate the data. First, check if your targetURL is accessible from within the PDF service container. Add some debugging by logging the page content before PDF generation. Make sure your containers are on the same Docker network and can communicate. What caught me off guard was that the frontend might be making API calls to localhost or relative URLs that don’t resolve correctly from the headless browser context. You might need proper service discovery or use fully qualified domain names for your API calls when running in Docker. The waitFor(8000) approach is unreliable for dynamic content. Wait for specific elements to appear instead or check if the API responses have actually populated your data arrays before generating the PDF.
docker containers often break cors and api endpoints. add --disable-web-security to your puppeteer launch args and verify your react app’s actually hitting the api successfully inside the container. debug this by throwing await webPage.evaluate(() => console.log(window.customerRecords)) before generating the pdf - you’ll see if the data’s actually there.
I had the exact same issue with React SPA content not showing up in Puppeteer PDFs when running in Docker. Your app works locally but breaks in Docker? That’s usually network problems mixed with timing issues. Ditch the waitFor(8000) - it’s unreliable. Instead, wait for specific DOM elements that show your data actually loaded. Use waitForSelector() to target elements that only appear after your API calls finish. Here’s what else helped me: Set up a health check endpoint in your React app that returns a ready status when all your critical data loads. Or even better - pre-render the content server-side or create a separate endpoint that spits out fully rendered HTML with data already there. This skips the client-side API calls completely during PDF generation.