/AirPdfPrinter

Virtual PDF AirPrint printer

Primary LanguageDockerfileApache License 2.0Apache-2.0

AirPdfPrinter

headline

Docker Hub

You wanna print or save something as PDF on your iOS device? Especially keeping those texts as they are, instead of being images. Well, Apple's iDevices don't come with such a feature by default, but don't worry, we provide you a neat solution here - a virtual PDF AirPrint printer!

Philosophy

To enable AirPrint of a printer, below requirements must be fulfilled, as described here.

  • The printer must be advertised with Bonjour broadcasting.

  • The printer must communicate with the client using IPP (Internet Printing Protocol).

HOWTO

  • Build

    # Assume you're in this project's root directory, where the Dockerfile is located
    docker build -t air-pdf-printer .
    
    # Build with argument, set your own admin password instead of the default one
    docker build --build-arg ADMIN_PASSWORD=<YourPassword> -t air-pdf-printer .
    
    # Or directly pull the image from Docker Hub
    docker pull thyrlian/air-pdf-printer

    The default admin username is root, and the default admin password is here.

  • Run

    # Run a container with interactive shell (you'll have to start CUPS print server on your own)
    docker run --network=host -it -v $(pwd)/pdf:/root/PDF -v $(pwd)/cups-pdf:/var/spool/cups-pdf --name air-pdf-printer air-pdf-printer /bin/bash
    
    # Run a container in the background
    docker run --network=host -d -v $(pwd)/pdf:/root/PDF -v $(pwd)/cups-pdf:/var/spool/cups-pdf --name air-pdf-printer air-pdf-printer
  • Notes

    • Multi-Arch: This Docker container would also work on ARM-based computer, you just need to build the Docker image properly. Here I'm not gonna talk about Docker's experimental feature buildx for multiple architectures support, you can find more information here and here on your own. In order to build for the appropriate CPU architecture, we can simply use the right base image in the Dockerfile.

      # Change base image to ARMv7 architecture
      sed -i.bak "s/FROM ubuntu:/FROM arm32v7\/ubuntu:/" Dockerfile && rm Dockerfile.bak
      
      # Change base image to x86_64 architecture
      sed -i.bak "s/FROM arm32v7\/ubuntu:/FROM ubuntu:/" Dockerfile && rm Dockerfile.bak
    • Network: With the option --network=host set, the container will use the Docker host network stack. When using host network mode, it would discard published ports, thus we don't need to publish any port with the run command (e.g.: -p 631:631 -p 5353:5353/udp). And in this way, we don't require dbus (a simple interprocess messaging system) package in the container. However, the dbus service is still needed on the host machine, and even it is deactivated, it would be automatically triggered to active when avahi-daemon starts running. For more information about Docker's network, please check here and here. Please be aware, the host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, as stated here.

    • Port: Apple is using UDP port 5353 to find capable services on your network via Bonjour automatically. Even though mDNS discovery uses the predefined port UDP 5353, application-specific traffic for services like AirPlay may use dynamically selected port numbers.

      Port TCP or UDP Service or protocol name RFC Service name Used by
      5353 UDP Multicast DNS (MDNS) 3927 mdns Bonjour, AirPlay, Home Sharing, Printer Discovery
  • Output

    CUPS-PDF output directory are defined under Path Settings which is located at /etc/cups/cups-pdf.conf. And the default path usually is: /var/spool/cups-pdf/${USER}

  • Troubleshoot

    • CUPS logs directory: /var/log/cups/

    • Start Avahi daemon with verbose debug level: avahi-daemon --debug

  • Commands

    # Run all init scripts, in alphabetical order, with the status command
    service --status-all
    
    # List units that systemd currently has in memory, with specified type and state
    systemctl list-units --type=service --state=active
    
    # Start CUPS service
    service cups start
    
    # Start Avahi mDNS/DNS-SD daemon
    service avahi-daemon start
    
    # Shows the server hostname and port.
    lpstat -H
    
    # Shows whether the CUPS server is running.
    lpstat -r
    
    # Shows all status information.
    lpstat -t
    
    # Shows all available destinations on the local network.
    lpstat -e
    
    # Shows the current default destination.
    lpstat -d
    
    # Display network connections, you need to have net-tools package installed
    netstat -ltup
    
    # Browse for all mDNS/DNS-SD services using the Avahi daemon and registered on the LAN
    avahi-browse -a -t
    
    # Find internet printing protocol printers
    ippfind
    ippfind --remote
  • Manage

    Web Interface: http://[IpAddressOfYourContainer]:631/

  • Add Printer

    • macOS: System Preferences -> Printers & Scanners -> Add (+) -> IP

      • Address: [IpAddressOfYourContainer]
      • Protocol: Internet Printing Protocol - IPP
      • Queue: printers/PDF (find the info here: http://[IpAddressOfYourContainer]:631/printers/)
      • Name: [YourCall]
      • Use: Generic PostScript Printer

    • iOS

License

Copyright (c) 2020 Jing Li. It is released under the Apache License. See the LICENSE file for details.

Attribution

The AirPrint-PDF.service static service XML file for Avahi is created via airprint-generate script.