我正在创建一个 Flask 应用程序,它使用 PDFkit 库从 HTML 字符串生成 PDF 文件。在本地运行代码时,它工作正常,但是当我尝试在 Docker 容器内运行它时,会出现此错误:
OSError: No wkhtmltopdf executable found: "C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe"
用于生成pdf的函数如下:
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
在此函数内,html_string 需要转换为 PDF 文件,运行时会生成上述错误。
我的 Dockerfile 如下所示:
FROM python:latest
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
WORKDIR /app
我正在使用 docker-compose.yml,因为我同时运行多个容器,我的 docker-compose.yml 文件:
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
我对 Docker 和一般编程都很陌生,我自己无法解决这个问题。我已经尝试了几个与此类似的问题的答案。最大的问题似乎是以适合我的项目的方式调整答案。
我在尝试过的其他问题中发现了一些事情: 将其添加到我的 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"]
这对于我的 docker-compose.yml 文件:
version: '3.8'
services:
wkhtmltopdf:
image: wkhtmltopdf
container_name: wkhtmltopdf
build:
dockerfile: Dockerfile
context: .
但是如果我同时拉动它似乎不起作用
FROM python:latest
FROM openjdk:8-jre-alpine
这会导致找不到 pip 或找不到 apk。
如何将 pdfkit/wkhtmltopdf 集成到我的项目中?
C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe
适用于 Windows,不会存在于 Linux Docker 容器中。
因此您需要将路径调整为容器中安装
wkhtmltopdf
的位置。
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
还更新 docker 文件以引用支持
pip
和 apk
的 docker 镜像。
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
这可能不是其他遇到此问题的人正在寻找的答案,因为它不再使用 pdfkit。
我以不同的方式实现了我的目标。决定不再使用 pdfkit 并开始使用 weasyprint (在我的例子中,我使用flask_weasyprint,因为我正在运行 Flask 应用程序,但 weasyprint 对于其他情况应该没问题)。
从 HTML 字符串生成 pdf 文件的功能:
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()