URL-to-PNG Docker Compose 部署指南

在 Ubuntu 22.04 用 Docker Compose 从零部署 URL-to-PNG v2.1.4:镜像选型、持久化、环境变量全表、等价 docker run、升级回滚与六个实测常见问题。

URL-to-PNGURL-to-PNGDockerDocker Compose自托管2026/10/31

URL-to-PNG Docker Compose 部署指南

目标:在 Ubuntu 22.04 服务器上用 Docker Compose 从零部署 URL-to-PNG v2.1.4 截图服务,包含镜像选型、数据持久化、环境变量全表、等价单命令与日常运维操作。全文命令与回显均在 Ubuntu 22.04 实测通过,服务部署后监听 8136 端口。

一、环境信息

  • 操作系统:Ubuntu 22.04 LTS(x86_64)
  • Docker:24.x(含 compose v2 插件,docker compose version 可验证)
  • 截图服务:URL-to-PNG v2.1.4(2026-10-31 实查为官方最新稳定版)
  • 对外端口:8136(服务内默认监听 3089,经端口映射对外提供 8136)
  • 部署目录:/opt/url-to-png/(compose 文件与缓存数据所在)
  • 缓存目录:/opt/url-to-png/data/images/(映射到服务内 /app/images)

二、镜像选型说明

官方发布两条镜像通道,版本号一致(2026-10-31 实查):

通道引用说明
GitHub Container Registryghcr.io/jasonraimondi/url-to-png官方 getting-started 默认引用
Docker Hubjasonraimondi/url-to-png国内拉取通常更快,本文实测采用

版本标签选择建议:

  • 固定小版本(如 :v2.1.4,本文采用):升级节奏自己掌控,生产推荐;
  • :latest:跟随上游,适合测试环境。

⚠️ 不要使用 v2.0.2 及更早版本:v2.0.3 修复了 file:// 协议任意文件读取安全问题,生产环境务必不低于 v2.0.3(版本演进细节见《URL-to-PNG 介绍与选型指南》第二章)。

⚠️ 网络说明:实测环境中 Docker Hub 直连超时,docker pull 需经代理完成(本环境代理为 192.168.1.62:7897,配置于 Docker 守护进程代理设置);无代理环境可改用国内镜像加速通道。

三、前置条件

  1. 服务器已安装 Docker 与 compose 插件:
docker --version
# Docker version 24.0.7, build afdd53b

docker compose version
# Docker Compose version v2.24.5
  1. 对外端口未被占用(本文用 8136):
ss -ltn | grep 8136 || echo "8136 可用"
# 8136 可用
  1. 目标网页可达:服务在渲染时会从服务器侧发起对目标 URL 的访问,请确认服务器出网策略允许。

四、部署步骤

4.1 创建部署目录与 compose 文件

mkdir -p /opt/url-to-png/data/images
vim /opt/url-to-png/docker-compose.yml

/opt/url-to-png/docker-compose.yml 全文(本文实测所用配置):

name: url-to-png

services:
  urltopng:
    image: jasonraimondi/url-to-png:v2.1.4
    container_name: urltopng-web
    restart: unless-stopped
    ports:
      - "8136:3089"
    environment:
      LOG_LEVEL: info
      NODE_ENV: production
      METRICS: "true"
      STORAGE_PROVIDER: filesystem
      IMAGE_STORAGE_PATH: /app/images
      CACHE_CONTROL: "public, max-age=86400, immutable"
    volumes:
      - ./data/images:/app/images

逐项说明:

  • image:固定 v2.1.4 版本标签,生产环境不追浮动标签;
  • ports:宿主 8136 → 服务 3089(3089 为 v2.0.0 起的默认端口);
  • METRICS: "true":开启 /metrics 连接池指标,容量观测需要;
  • STORAGE_PROVIDER: filesystem + IMAGE_STORAGE_PATH: /app/images:渲染结果缓存到本地磁盘;
  • volumes:把宿主 ./data/images(即 /opt/url-to-png/data/images)挂为缓存目录,服务重启缓存不丢;
  • restart: unless-stopped:异常退出自动拉起。

4.2 拉取镜像并启动

cd /opt/url-to-png
docker compose pull
# [+] Pulling 1/1
#  ✔ urltopng Pulled                                    8.9s

docker compose up -d
# [+] Running 2/2
#  ✔ Network url-to-png_default    Created              0.1s
#  ✔ Container urltopng-web        Started              0.6s

4.3 验证服务就绪

docker compose ps
# NAME           IMAGE                            COMMAND                  SERVICE    CREATED          STATUS          PORTS
# urltopng-web   jasonraimondi/url-to-png:v2.1.4  "docker-entrypoint.s…"   urltopng   5 seconds ago    Up 4 seconds    0.0.0.0:8136->3089/tcp, [::]:8136->3089/tcp

curl -s http://localhost:8136/ping
# "pong"

再发第一张真实截图(默认 250x250):

curl -s 'http://localhost:8136/?url=https://example.com&forceReload=true' -o first.png
file first.png
# first.png: PNG image data, 250 x 250, 8-bit/color RGB, non-interlaced

能看到 PNG 尺寸即部署完成。首次启动后可顺手确认缓存目录已开始工作:

ls /opt/url-to-png/data/images/
# 10-31-2026.httpsexamplecom_forcereload-true.png

💡 缓存文件名即 imageId:日期.URL与参数的 slug 化串.png,参数一变文件名就变(机制详见 D5 篇)。

五、数据持久化说明

URL-to-PNG 的"数据"只有一类:渲染结果缓存。本文配置下全部落在宿主 /opt/url-to-png/data/images/:

  • 重启不丢:缓存文件落在宿主 bind mount 目录,服务重启后同参数请求依然毫秒级命中(实测重启后首请求 0.014s 返回同尺寸缓存图);
  • 可以整目录备份:tar czf urltopng-cache-$(date +%F).tgz -C /opt/url-to-png/data images;
  • 可以整目录清理:删光目录内文件即可释放空间,服务无需重启,下一请求自动重建缓存;
  • 容量增长注意:每种「URL+参数」组合各存一个文件且无自动清理,长期运行建议按月巡检 du -sh(见 8.2 节)。

若改用 s3 后端(STORAGE_PROVIDER=s3 + AWS_* 环境变量),本地目录不再是数据权威副本,多实例可共享同一缓存。

六、环境变量表

官方支持的环境变量全项(官方文档 Configuration 页 + v2.1.4 实测核对):

环境变量默认值说明
LOG_LEVELdebug日志级别:debug / info / warn / error
NODE_ENVdevelopmentNode 运行环境,生产建议 production
PORT3089服务监听端口(改了需同步改 ports 映射)
CACHE_CONTROLpublic, max-age=86400, immutable截图响应的 Cache-Control 头
ALLOW_LIST空(全放行)白名单,逗号分隔 host,精确匹配
BLOCK_LIST空(全放行)黑名单,逗号分隔 host,精确匹配
BROWSER_TIMEOUT10000渲染超时(毫秒),超时返回 500
BROWSER_WAIT_UNTILdomcontentloaded页面加载等待事件:load / domcontentloaded / networkidle
POOL_IDLE_TIMEOUT_MS15000浏览器实例空闲回收时间(毫秒)
POOL_MAX10浏览器池上限
POOL_MAX_WAITING_CLIENTS50等待队列上限
POOL_MIN2浏览器池常驻下限
DEFAULT_WIDTH / DEFAULT_HEIGHT250默认输出宽高
DEFAULT_VIEWPORT_WIDTH / DEFAULT_VIEWPORT_HEIGHT1080默认渲染视口
DEFAULT_IS_MOBILE / DEFAULT_IS_FULL_PAGE / DEFAULT_IS_DARK_MODEfalse默认布尔渲染开关
DEFAULT_DEVICE_SCALE_FACTOR1默认 DPR
METRICSfalse是否开启 /metrics
CRYPTO_KEY空AES-GCM 256 加密密钥(JWK JSON 串),配置后只收加密请求
STORAGE_PROVIDERstub存储后端:stub / filesystem / s3 / couchdb
IMAGE_STORAGE_PATH—filesystem 后端的存储目录
AWS_BUCKET / AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_DEFAULT_REGION / AWS_FORCE_PATH_STYLE / AWS_ENDPOINT_URL_S3—s3 后端参数
COUCH_DB_PROTOCOL / COUCH_DB_USER / COUCH_DB_PASS / COUCH_DB_HOST / COUCH_DB_PORT / COUCHDB_DATABASE—couchdb 后端参数

各变量分类详解、名单匹配与超时实测见《URL-to-PNG 2.1.4 配置参数详解》。

七、配置文件挂载与配置调整

URL-to-PNG 没有配置文件,全部配置走环境变量(上表),因此无需挂载任何 conf/yaml:

  • 改配置 = 改 compose 的 environment: 段 → docker compose up -d 重建生效;
  • 服务内唯一有状态目录是缓存目录 /app/images(已挂出);
  • 验证环境变量生效的实测方法——以 METRICS 为例,改后重建并探测:
curl -s http://localhost:8136/metrics
# {"poolMetrics":{"spareResourceCapacity":8,"size":2,"available":2,"borrowed":0,"pending":0,"max":10,"min":2}}

min: 2 / max: 10 即 POOL_MIN/POOL_MAX 的生效值;若把 METRICS 关掉,该端点返回 404。

八、常用运维命令

以下命令均在 /opt/url-to-png 目录执行。

8.1 状态与日志

docker compose ps
# NAME           IMAGE                            ...  STATUS        PORTS
# urltopng-web   jasonraimondi/url-to-png:v2.1.4  ...  Up 2 hours    0.0.0.0:8136->3089/tcp

docker compose logs --tail 5 urltopng
# {"level":30,"time":1793408061674,"pid":1,"hostname":"...","name":"url-to-png","msg":"Allowed Domains: (none)"}
# {"level":30,"time":1793408061674,"pid":1,"hostname":"...","name":"url-to-png","msg":"Server is running on port http://localhost:3089/ping"}

日志为 JSON 行(pino 格式),level 30=info、40=warn、50=error;被名单拦截的请求会输出 Blocked request to ... 警告行。

8.2 缓存巡检与清理

du -sh /opt/url-to-png/data/images/
# 1.8M    /opt/url-to-png/data/images/

ls /opt/url-to-png/data/images/ | wc -l
# 18

# 全量清空(服务不停)
rm -f /opt/url-to-png/data/images/*.png

8.3 升级版本

# 1. 改 compose 中 image 标签为新版本号
sed -i 's|jasonraimondi/url-to-png:v2.1.4|jasonraimondi/url-to-png:<新版本>|' docker-compose.yml
# 2. 拉新镜像并重建(缓存目录不受影响)
docker compose pull && docker compose up -d
# 3. 回归验证
curl -s http://localhost:8136/ping ; echo
curl -s 'http://localhost:8136/?url=https://example.com&forceReload=true' -o /dev/null -w '%{http_code}\n'
# 200

升级回滚:把 image 标签改回旧版本号,重复第 2、3 步即可;缓存文件与版本无关,无需清理。

8.4 停止与卸载

docker compose down      # 停止并移除服务网络(缓存数据保留在宿主目录)
# 完全卸载:docker compose down 后 rm -rf /opt/url-to-png

九、等价 docker run

不使用 Compose 时的等价单命令(与 4.1 compose 语义一致):

docker run -d \
  --name urltopng-web \
  --restart unless-stopped \
  -p 8136:3089 \
  -e LOG_LEVEL=info \
  -e NODE_ENV=production \
  -e METRICS=true \
  -e STORAGE_PROVIDER=filesystem \
  -e IMAGE_STORAGE_PATH=/app/images \
  -e CACHE_CONTROL="public, max-age=86400, immutable" \
  -v /opt/url-to-png/data/images:/app/images \
  jasonraimondi/url-to-png:v2.1.4

启动后同样以 curl -s http://localhost:8136/ping 验证(实测返回 "pong")。多实例或长期维护仍建议用 Compose(声明式、可复制)。

十、常见问题

Q1:截图请求返回 500,日志里是 page.goto: Timeout ... exceeded?

渲染耗时超过 BROWSER_TIMEOUT(默认 10 秒)。实测把 BROWSER_TIMEOUT 压到 2000 后请求 example.com,可稳定复现:

{"message":"page.goto: Timeout 2000ms exceeded.\nCall log:\n  - navigating to \"https://example.com/\", waiting until \"domcontentloaded\"\n"}

解决:按目标站点最慢耗时放宽 BROWSER_TIMEOUT;或接受失败让调用方重试。

Q2:目标域名渲染失败,日志报 ERR_NAME_NOT_RESOLVED?

服务器侧解析不了目标域名(实测对不存在域名返回):

{"message":"page.goto: net::ERR_NAME_NOT_RESOLVED at https://nonexistent.invalid/\nCall log:\n  - navigating to \"https://nonexistent.invalid/\", waiting until \"domcontentloaded\"\n"}

排查服务器 DNS 与出网策略,而非截图服务本身。

Q3:请求被 403 拒绝:{"message":"Access to this URL is forbidden"}?

命中了 ALLOW_LIST/BLOCK_LIST。注意名单是 host 精确匹配:白名单 example.com 不会放行 www.example.com(实测两者回显一致)。把需要的全部 host 逐个列入,或清空名单恢复全放行。

Q4:首次请求比缓存命中慢很多(约 1-5 秒)?

正常现象:缓存未命中需真实渲染(含浏览器取页面、等资源、截图、缩放全链路);命中后毫秒级返回(实测 0.0015s)。含慢资源的页面首图耗时约等于最慢资源耗时(实测 5 秒慢图页返回耗时 5.1 秒),完整实验数据见《URL-to-PNG 2.1.4 API 使用详解》。

Q5:缓存目录写入失败?

镜像内服务以非 root 运行账号(pwuser)写 /app/images。若 bind mount 的宿主目录权限过窄会出现 EACCES,实测正常启动时宿主目录属主会被调整为该运行账号;也可手动 chown -R 1000:1000 /opt/url-to-png/data/images 兜底。

Q6:8136 端口被其他服务占用?

ss -ltn | grep 8136 找到占用方;要么换 compose ports 左侧端口(如 "8200:3089"),要么停掉占用服务后重新 up -d。

十一、参考链接

URL-to-PNG Docker Compose 部署指南 - Quzuo