skip to Main Content

I am creating a Flask app that uses the library PDFkit to generate a PDF file from a HTML string. When running the code locally it works fine, however when I try to run it inside a Docker container this error comes up:

OSError: No wkhtmltopdf executable found: "C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe"

The function used to generate the pdf is given below:

def generate_pdf_schedule(schedules):
    html_string = schedule_to_html_string(schedules)

    config = pdfkit.configuration(wkhtmltopdf='C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe')

    pdf = pdfkit.from_string(html_string, configuration=config)

    return pdf

Inside this function the html_string needs to be converted to a PDF file, when this is running it generates the above mentioned error.

My Dockerfile looks like this:

FROM python:latest

ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt


WORKDIR /app

I am using a docker-compose.yml as I have several containers running at once, my docker-compose.yml file:

services:
  redis:
    image: redis
    ports:
      - '6379:6379'
  web:
    build:
      context: .
    environment:
      FLASK_APP: app
      FLASK_DEBUG: 1
    volumes:
      - .:/app
    command: flask run -h 0.0.0.0
    ports:
      - 5000:5000
  celery:
    build:
        context: .
    environment:
      FLASK_APP: app
    volumes:
      - .:/app
    command: celery -A app.celery worker --loglevel=info
    depends_on:
      - redis

I am really new to Docker and programming in general, couldn’t figure this out on my own. I have tried several answers on questions that are alike to this one. The biggest issue seems to be adjusting the answers in such a way that it suits my project.

Some things I found in other questions that I have tried:
Adding this to my Dockerfile

# https://stackoverflow.com/a/62737156/152016
# Create image based on the official openjdk 8-jre-alpine image from the dockerhub
FROM openjdk:8-jre-alpine

# Install wkhtmltopdf
# https://stackoverflow.com/a/56925361/152016
RUN apk add --no-cache wkhtmltopdf ttf-dejavu

ENTRYPOINT ["sh"]

And this to my docker-compose.yml file:

version: '3.8'

services:
  wkhtmltopdf:
    image: wkhtmltopdf
    container_name: wkhtmltopdf
    build:
      dockerfile: Dockerfile
      context: .

However it seems to not work if I pull both

FROM python:latest
FROM openjdk:8-jre-alpine

this results in either pip not being found or apk not being found.

How can I integrate pdfkit/wkhtmltopdf to my project?

2

Answers


  1. Chosen as BEST ANSWER

    This may not be the answer other people encountering this problem are searching for since it no longer uses pdfkit.

    I accomplished my goal on a different way. Decided to no longer use pdfkit and started using weasyprint (in my case I used flask_weasyprint since I am running a flask app, but weasyprint should be fine for other cases).

    Function to generate pdf file from HTML string:

    from weasyprint import HTML
    
    
    def makepdf(html):
        """Generate a PDF file from a string of HTML."""
        htmldoc = HTML(string=html, base_url="")
        return htmldoc.write_pdf()
    

  2. C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe is for Windows and won’t exist in a Linux Docker container.

    So you’ll need to adjust the path to where wkhtmltopdf is installed in the container.

    def generate_pdf_schedule(schedules):
        html_string = schedule_to_html_string(schedules)
    
        # Adjust the path for wkhtmltopdf based on its location in the Alpine container
        config = pdfkit.configuration(wkhtmltopdf='/usr/bin/wkhtmltopdf')
    
        pdf = pdfkit.from_string(html_string, configuration=config)
    
        return pdf
    

    Also update the docker file to reference the docker image that supports pip and apk.

    FROM python:3.8-alpine
    
    ENV PYTHONUNBUFFERED=1
    ENV PYTHONDONTWRITEBYTECODE=1
    
    # Install dependencies
    RUN apk add --no-cache wkhtmltopdf ttf-dejavu
    COPY requirements.txt /app/
    RUN pip install --no-cache-dir -r /app/requirements.txt
    
    # Set work directory
    WORKDIR /app
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search