Wkhtmltopdf with Docker Compose for PDFs: Invoices, Email Attachments & Print Designer

Hi everyone,

I’m working with Docker Compose to set up Frappe and I’m looking for guidance on integrating wkhtmltopdf to:

  1. Generate PDF invoices
  2. Attach PDFs to emails
  3. Print custom PDF designs using the Print Designer app

Has anyone successfully set up wkhtmltopdf in a Docker Compose environment to handle these tasks? If so, I’d love to know more about the configuration steps or any tips to ensure it runs smoothly.

Thanks in advance for any insights or advice!

Traceback with variables (most recent call last):
  File "apps/frappe/frappe/core/doctype/file/utils.py", line 368, in attach_files_to_document
    file.insert(ignore_permissions=True)
      doc = <PDPrintFormat: Sales Invoice PD Format v2>
      event = 'on_update'
      attach_fields = [<Attach ImageDocField: print_designer_preview_img parent=Print Format>]
      df = <Attach ImageDocField: print_designer_preview_img parent=Print Format>
      value = '/private/files/print_designer-sales_invoice_pd_format_v2-preview33003c.jpg'
      unattached_file = None
      file = <File: unsaved>
  File "apps/frappe/frappe/model/document.py", line 285, in insert
    self.run_method("before_insert")
      self = <File: unsaved>
      ignore_permissions = True
      ignore_links = None
      ignore_if_duplicate = False
      ignore_mandatory = None
      set_name = None
      set_child_names = True
  File "apps/frappe/frappe/model/document.py", line 962, in run_method
    out = Document.hook(fn)(self, *args, **kwargs)
      self = <File: unsaved>
      method = 'before_insert'
      args = ()
      kwargs = {}
      fn = <function Document.run_method.<locals>.fn at 0x7fbd5cb46160>
  File "apps/frappe/frappe/model/document.py", line 1322, in composer
    return composed(self, method, *args, **kwargs)
      self = <File: unsaved>
      args = ()
      kwargs = {}
      hooks = []
      method = 'before_insert'
      doc_events = {'*': {'on_update': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.core.doctype.file.utils.attach_files_to_document', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply', 'frappe.automation.doctype.assignment_rule.assignment_rule.update_due_date', 'frappe.core.doctype.user_type.user_type.apply_permissions_for_non_standard_user_type'], 'after_rename': ['frappe.desk.notifications.clear_doctype_notifications'], 'on_cancel': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply'], 'on_trash': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions'], 'on_update_after_submit': ['frappe.workflow.doctype.workflow_action.workflow_action.process_w...
      composed = <function Document.hook.<locals>.compose.<locals>.runner at 0x7fbd5cb46020>
      compose = <function Document.hook.<locals>.compose at 0x7fbd5cb462a0>
      f = <function Document.run_method.<locals>.fn at 0x7fbd5cb46160>
  File "apps/frappe/frappe/model/document.py", line 1304, in runner
    add_to_return_value(self, fn(self, *args, **kwargs))
      self = <File: unsaved>
      method = 'before_insert'
      args = ()
      kwargs = {}
      add_to_return_value = <function Document.hook.<locals>.add_to_return_value at 0x7fbd5cb45d00>
      fn = <function Document.run_method.<locals>.fn at 0x7fbd5cb46160>
      hooks = ()
  File "apps/frappe/frappe/model/document.py", line 959, in fn
    return method_object(*args, **kwargs)
      self = <File: unsaved>
      args = ()
      kwargs = {}
      method_object = <bound method File.before_insert of <File: unsaved>>
      method = 'before_insert'
  File "apps/frappe/frappe/core/doctype/file/file.py", line 104, in before_insert
    self.save_file(content=self.get_content())
      self = <File: unsaved>
  File "apps/frappe/frappe/core/doctype/file/file.py", line 539, in get_content
    with open(file_path, mode="rb") as f:
      self = <File: unsaved>
      file_path = './test.menteware.com/private/files/print_designer-sales_invoice_pd_format_v2-preview33003c.jpg'
builtins.FileNotFoundError: [Errno 2] No such file or directory: './test.menteware.com/private/files/print_designer-sales_invoice_pd_format_v2-preview33003c.jpg'