CLI as Docker container

The zplCloud remote agent as a Docker container - for Raspberry Pi, Synology NAS and any Docker host. No inbound ports, no firewall changes.

What is the Docker agent and what is it good for?

The zplcloud-agent is the zplcloud CLI as a prebuilt container. It runs on a machine near your Zebra printers and connects outbound to api.zplcloud.com - similar to TeamViewer. Afterwards you can create printers in the zplCloud "Remote Printers" tab and forward print jobs, profiles and probes via the agent to the printers in your local LAN (TCP 9100) or to USB printers.

  • No inbound ports - only one outbound HTTPS/WebSocket connection, works behind NAT and firewalls.
  • One container instead of a file path - ideal for Raspberry Pi (64-bit), Synology, Intel/Apple-Silicon-Mac with Docker Desktop.
  • Multi-arch image - linux/amd64 + linux/arm64, public, no login.
  • USB printers - ZPL via USB virtual COM ports (CDC-ACM) or libusb (printer class).
  • Autostart & logs - restart: unless-stopped, optional daily log file.

Prerequisites

  • Docker (Desktop, Docker Engine or Synology Container Manager).
  • An API key from the zplCloud API tab.
  • Printers reachable in the same LAN (TCP 9100) or connected via USB.

docker-compose.agent.yml

Download the file (or copy it) and adjust ZPLCLOUD_API_KEY and ZPLCLOUD_AGENT:

# docker-compose.agent.yml
services:
  zplcloud-agent:
    image: docker.zplcloud.com/zplcloud-agent:latest
    container_name: zplcloud-agent
    restart: unless-stopped
    environment:
      ZPLCLOUD_API_KEY: "sk_zplcloud_CHANGE_ME"     # API tab
      ZPLCLOUD_AGENT: "PI"                           # Name in the Remote Printers tab
      ZPLCLOUD_API_BASE: "https://api.zplcloud.com"  # public backend (outbound)
      ZPLCLOUD_VERBOSE: "false"                      # true = SignalR/debug trace
      ZPLCLOUD_LOG: "true"                           # write zplcloud-<yyyy-MM-dd>.log
      ZPLCLOUD_LOG_DIR: "/logs"
      ZPLCLOUD_TIMEOUT: "5000"
    volumes:
      - agent-logs:/logs
      # Raw USB bus (needed for libusb to detect/address the Zebra printer)
      - /dev/bus/usb:/dev/bus/usb
    # Simplest USB path (works for printer class AND CDC-ACM serial)
    privileged: true
    # Safer alternative (remove privileged, then use a udev rule):
    # devices:
    #   - "/dev/bus/usb:/dev/bus/usb:rwm"
    #   - "/dev/ttyACM0:/dev/ttyACM0:rwm"
    #   - "/dev/ttyUSB0:/dev/ttyUSB0:rwm"

volumes:
  agent-logs:

Environment variables (all parameters)

VariableRequiredMeaning
ZPLCLOUD_API_KEYyesAPI key from the zplCloud API tab; authenticates the agent to the backend.
ZPLCLOUD_AGENTyesDisplay name in the "Remote Printers" tab (free choice, e.g. "Warehouse Berlin", "PI").
ZPLCLOUD_API_BASEnoBase URL (default: https://api.zplcloud.com).
ZPLCLOUD_VERBOSEnotrue = SignalR negotiation/transport trace (troubleshooting).
ZPLCLOUD_LOGnotrue = writes zplcloud-<yyyy-MM-dd>.log into ZPLCLOUD_LOG_DIR.
ZPLCLOUD_LOG_DIRnoLog directory inside the container (e.g. /logs, mounted via volume).
ZPLCLOUD_TIMEOUTnoConnect/read timeout in ms (default: 5000).

Start & manage

# Start (background, autostart)
docker compose -f docker-compose.agent.yml up -d

# Follow logs live
docker compose -f docker-compose.agent.yml logs -f zplcloud-agent

# Restart (e.g. after an API key change)
docker compose -f docker-compose.agent.yml restart

# Pull latest image + restart (update)
docker compose -f docker-compose.agent.yml pull
docker compose -f docker-compose.agent.yml up -d

# Stop / remove
docker compose -f docker-compose.agent.yml down

Supported platforms

  • linux/amd64 - x64 Linux, x64 Synology, Intel Docker hosts, Windows Docker (WSL2).
  • linux/arm64 - 64-bit Raspberry Pi (Pi OS 64-bit), ARM Synology, Apple Silicon Docker.
  • 32-bit Raspberry Pi: no 32-bit ARM image → use the direct installer instead.

USB printers in the container

  • Simplest way: privileged: true - works for the USB printer class (libusb) and CDC-ACM serial.
  • Safer: remove privileged and mount the devices explicitly (devices: above, commented out) plus a udev rule, e.g. GROUP="dialout", MODE="0660" for the Zebra printer.

Troubleshooting

SymptomSolution
Agent does not appear onlineCheck ZPLCLOUD_API_KEY, inspect the logs (docker compose logs -f), set ZPLCLOUD_VERBOSE=true for a trace.
USB printer not reachableSet privileged: true or configure devices + udev rule; /dev/bus/usb must be mounted.
TCP 9100 not reachableCheck the printer IP/host in the Remote Printers tab; printer and container must be in the same LAN.