N1 盒子做打印服务器:Docker CUPS + HP CP1025 完整记录
背景
最近从本地淘了一台 HP LaserJet CP1025 彩色激光打印机,USB 接口的,每次打印都必须要开电脑。之前了解到如果要实现无线打印需要一个小白学习盒子,后来从网上搜有办法可以实现无线打印;
手头正好有一台 N1 盒子,刷了 OpenWrt 当旁路由用。
想法很简单:N1 盒子一直开着,USB 口闲着,打印机挂上去,Docker 跑个 CUPS 服务,整个局域网都能打印,手机也能通过 AirPrint 直接打。
看起来是个十来分钟能搞定的活。实际上折腾了大半天。这里所有命令和日志都是AI帮我实现的,全程没有敲一个代码,因为我不是程序员哈哈哈
一个办法就是通过 openwrt 内的 usb 网络打印,电脑可以无线,但是ios、安卓无法实现无线打印
另一个办法是安装CUPS实现原生AirPrint
踩坑记录
搜了一圈,找到 chuckcharlie/cups-avahi-airprint 这个 Docker 镜像,自带 AirPrint 和 Avahi 服务发现。
拉镜像、创建容器、打开 CUPS 后台(http://N1的IP:631)、添加打印机——USB 口确实检测到了 CP1025,驱动列表里也有 HP LaserJet CP 1025, hpcups 3.26.4,选它,点打印测试页。
卡住了。状态显示 "Filter failed"。
查日志,关键报错:
hplip.plugin-error
m_Job initialization failed with error = 48
PID xxx (/usr/lib/cups/filter/hpcups) crashed on signal 11.
hpcups 驱动需要 HP 的专有二进制插件,没装这个就直接崩。
然后开始了一段漫长且痛苦的尝试:
hp-plugin命令——容器里根本没这个命令从 SourceForge 下载
hplip-3.26.4-plugin.run——这个版本压根没发布独立插件文件从 HPLIP 完整包里找
plugin.py手动运行——脚本用了 Python 2 的URLopener,新版 Python 不兼容手动拷贝
.so文件到/usr/share/hplip/prnt/plugins/——hplip 有验证机制,光拷文件不行
全堵死了。
后来在树莓派论坛看到有人说 HP CP1025 用 foo2zjs 开源驱动能正常打印,不需要 HP 任何专有插件。试了一下,果然成了。
这里感谢这篇文章的教程,同样适合部署在 nas 里:https://4ft35t.github.io/post/hp-cp1025-set-airprint-on-dsm7-via-docker-cups/
下面是重新来的完整步骤。
第一步:创建 CUPS 容器
docker run -d
--name=airprint
--restart=always
--net=host
--privileged=true
-e TZ="Asia/Shanghai"
-e CUPSADMIN="admin"
-e CUPSPASSWORD="pass"
-e HOST_OS="OpenWrt"
-e TCP_PORT_631="631"
-v /var/run/dbus:/var/run/dbus
-v /var/lib/docker/data/cups/config:/config
-v /var/lib/docker/data/cups/services:/services
-v /dev/bus/usb:/dev/bus/usb
chuckcharlie/cups-avahi-airprint:latest
参数说明:
--net=host— 用宿主机网络,AirPrint 的 mDNS 广播靠这个--privileged=true— 访问 USB 设备需要特权模式-v /var/run/dbus— Avahi 做局域网服务发现要用 D-Bus-v /dev/bus/usb— USB 打印机设备映射进容器CUPSADMIN/CUPSPASSWORD— CUPS 后台的登录账号密码
跑起来之后确认一下:
docker ps
看到 airprint 容器状态是 Up 就行。
第二步:进容器装编译工具
这个镜像是基于 Alpine Linux 的,没有 apt,用 apk。而且没有 bash,只能用 sh:
docker exec -it airprint sh
装编译需要的东西:
apk add --no-cache make gcc g++ libc-dev cups-dev git
装完确认一下:
which make && which gcc && make --version | head -1
输出 GNU Make x.x.x 就行。
第三步:下载 foo2zjs 源码
cd /tmp
wget "https://github.com/koenkooi/foo2zjs/archive/refs/heads/master.tar.gz" -O foo2zjs.tar.gz
我这边 N1 容器内直接从 GitHub 下载是成功的。如果你的环境连 GitHub 不通(N1 的 OpenSSL 有时候会跟某些 HTTPS 站点握手失败),就在电脑浏览器打开上面那个地址下载,然后传进去:
# 电脑上
scp master.tar.gz root@N1的IP:/tmp/
# N1 宿主机上
docker cp /tmp/master.tar.gz airprint:/tmp/foo2zjs.tar.gz
第四步:编译安装
tar xzf foo2zjs.tar.gz
cd foo2zjs-master
make
编译过程会输出一大堆东西,中间会有 warning 和 date: invalid date 之类的,不影响,忽略。只要最后没报 Error 停下来就行。
然后安装:
make install
又是大量输出,看到一堆 # Install ... 的信息就说明装好了。
第五步:重启 CUPS
kill -HUP $(pidof cupsd)
不用重启容器,这行就够。
第六步:添加打印机
浏览器访问 http://N1的IP:631,用你创建容器时设的账号密码登录(我设的是 admin / pass)。
点 Administration → Add Printer
系统会检测到 USB 打印机,选 HP LaserJet CP 1025
给打印机起个名字,勾上 Share This Printer(共享给局域网)
选驱动的时候,往下翻,找这个:
HP LaserJet Pro CP1025nw Foomatic/foo2zjs-z3 (en)不要选 hpcups 开头的那个。虽然型号写的是 CP1025nw,但 CP1025 和 CP1025nw 用的是同一套 foo2zjs 驱动,选它就行。
点 Add Printer 完成
在打印机页面点 Print Test Page,能打出来就搞定了。
客户端连接
Windows
设置 → 蓝牙和设备 → 打印机和扫描仪 → 添加设备。
系统会自动发现 HP LaserJet CP 1025 @ airprint,直接添加就行,Windows 会自己下载驱动。

iPhone / iPad / Mac
什么都不用配。AirPrint 是系统级支持,任何 App 里点"打印"都能看到这台打印机。

Linux
装个 cups-browsed 就能自动发现:
sudo apt install cups-browsed
第七步:构建自定义镜像(一步到位,解决重启后打印机丢失的问题)
前面六步做完,打印机能用了。但有个大坑:OpenWrt 重启后,打印机配置会丢失。
原因是容器的 /root 和 /tmp 是 tmpfs(内存文件系统),重启后文件全部消失。宿主机挂载的 /config 目录在某些情况下也会被清空。
用 Dockerfile 把 foo2zjs 驱动、打印机配置、PPD 文件、恢复脚本全部打进镜像层,彻底解决。
7.1 导出打印机配置和 PPD 文件
docker exec airprint sh -c "cat /etc/cups/printers.conf" > /tmp/printers.conf
docker exec airprint sh -c "cat /config/ppd/HP_LaserJet_CP_1025.ppd" > /tmp/HP_LaserJet_CP_1025.ppd
确认两个文件都有内容(空文件会导致后面 COPY 进镜像的也是空的):
head -3 /tmp/printers.conf
head -3 /tmp/HP_LaserJet_CP_1025.ppd
7.2 写 Dockerfile
cat > /tmp/Dockerfile << 'DOCKERFILE'
FROM chuckcharlie/cups-avahi-airprint:latest
# 编译安装 foo2zjs 驱动
RUN apk add --no-cache make gcc g++ libc-dev cups-dev &&
cd /tmp &&
wget "https://github.com/koenkooi/foo2zjs/archive/refs/heads/master.tar.gz" -O foo2zjs.tar.gz &&
tar xzf foo2zjs.tar.gz &&
cd foo2zjs-master &&
make && make install &&
cd / && rm -rf /tmp/foo2zjs* &&
apk del make gcc g++ libc-dev cups-dev
# 打印机配置和 PPD 文件写入镜像层
COPY printers.conf /etc/cups/printers.conf.default
COPY HP_LaserJet_CP_1025.ppd /etc/cups/ppd.default/HP_LaserJet_CP_1025.ppd
# 恢复脚本:开机时如果宿主机配置或 PPD 为空,从镜像备份恢复
RUN echo '#!/bin/sh' > /etc/cups/init-printers.sh &&
echo 'if [ ! -s /config/printers.conf ] && [ -f /etc/cups/printers.conf.default ]; then' >> /etc/cups/init-printers.sh &&
echo ' cp /etc/cups/printers.conf.default /config/printers.conf' >> /etc/cups/init-printers.sh &&
echo 'fi' >> /etc/cups/init-printers.sh &&
echo 'if [ ! -f /config/ppd/HP_LaserJet_CP_1025.ppd ] && [ -f /etc/cups/ppd.default/HP_LaserJet_CP_1025.ppd ]; then' >> /etc/cups/init-printers.sh &&
echo ' mkdir -p /config/ppd' >> /etc/cups/init-printers.sh &&
echo ' cp /etc/cups/ppd.default/HP_LaserJet_CP_1025.ppd /config/ppd/HP_LaserJet_CP_1025.ppd' >> /etc/cups/init-printers.sh &&
echo 'fi' >> /etc/cups/init-printers.sh &&
chmod +x /etc/cups/init-printers.sh
# 在启动脚本 set -x 后面插入恢复脚本
RUN sed -i '/^set -x$/a /etc/cups/init-printers.sh' /root/run_cups.sh
DOCKERFILE
7.3 构建镜像
需要几分钟(下载 foo2zjs 源码并编译):
docker build -t cups-foo2zjs /tmp/
构建完后把构建文件存到持久目录(/tmp 是 tmpfs,OpenWrt 重启后文件就没了):
mkdir -p /var/lib/docker/data/cups/dockerbuild
cp /tmp/Dockerfile /tmp/printers.conf /tmp/HP_LaserJet_CP_1025.ppd /var/lib/docker/data/cups/dockerbuild/
以后重建镜像就用:
docker build -t cups-foo2zjs /var/lib/docker/data/cups/dockerbuild/
7.4 重建容器并验证
docker stop airprint && docker rm airprint
docker run -d
--name=airprint
--restart=always
--net=host
--privileged=true
-e TZ="Asia/Shanghai"
-e CUPSADMIN="admin"
-e CUPSPASSWORD="pass"
-e HOST_OS="OpenWrt"
-e TCP_PORT_631="631"
-v /var/run/dbus:/var/run/dbus
-v /var/lib/docker/data/cups/config:/config
-v /var/lib/docker/data/cups/services:/services
-v /dev/bus/usb:/dev/bus/usb
cups-foo2zjs
验证 PPD 和配置:
docker exec airprint sh -c "ls /config/ppd/ && cat /etc/cups/printers.conf | grep -c Printer"
输出 PPD 文件名和 1 说明成功。试打测试页确认能打印,然后重启 OpenWrt 做最终验证。
备忘
踩过的坑,记一下:
hpcups 驱动(hplip)需要 HP 专有插件,Alpine 容器里基本装不上。别折腾了,直接用 foo2zjs
Alpine 的 apk 源有时候会抽风(403、Permission denied),默认源能用就用默认源,别换国内镜像
N1 的 OpenSSL 连部分 HTTPS 站点会握手失败(ghp.ci、SourceForge 都试过不行),GitHub 主站倒是能连
plugin.py依赖 Python 2 的URLopener,新版 Python 不兼容,改 Python 代码更麻烦,不如直接编译 foo2zjs选驱动的时候看清楚:要选带 foo2zjs 字样的,不要选 hpcups
/root和/tmp是 tmpfs(内存文件系统),重启后文件丢失,docker commit也无法保存这些目录的内容docker cp在这个容器里有权限问题,用docker exec sh -c "cp ..."绕过Dockerfile 构建时,
COPY的文件必须确认有内容,否则 COPY 进去的是空文件PPD 文件(
/config/ppd/)也会在重建容器时丢失,必须一并打进镜像构建文件(Dockerfile + printers.conf + PPD)要存到持久目录
/var/lib/docker/data/cups/dockerbuild/
作者提示含AI生成内容。作者声明本文无利益相关,欢迎值友理性交流,和谐讨论~

赞赞赞赞赞
校验提示文案
真实小白
校验提示文案
值友3478925946
校验提示文案
Master0123
校验提示文案
林雨梦
校验提示文案
小糖017
校验提示文案
值友2565893140
校验提示文案
值友2565893140
校验提示文案
小糖017
校验提示文案
Master0123
校验提示文案
值友3478925946
校验提示文案
真实小白
校验提示文案
林雨梦
校验提示文案
赞赞赞赞赞
校验提示文案