PictShare 3.7.5 Docker Compose 部署指南

在 Linux 服务器上用 Docker Compose 部署 PictShare 3.7.5,覆盖镜像选型、端口规划、首启验证、上传实测与数据持久化全流程。

PictSharePictShareDockerDocker Compose自托管2026/10/31

PictShare 3.7.5 Docker Compose 部署指南

目标:在 Linux 服务器上以 Docker Compose 单服务栈部署 PictShare 3.7.5,完成镜像选型、端口与子网规划、首启验证、图片/视频上传与外链缩放全链路实测,以及数据持久化与日常运维命令。已在 Ubuntu 22.04(x86_64)服务器实测通过,镜像 hascheksolutions/pictshare:3.7.5(PHP 8.4.27/FrankenPHP,内置 Redis 与 ffmpeg)。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64,内核 5.15+)
  • 软件版本:PictShare 3.7.5(官方最新稳定版 tag v3.7.5,查询日期 2026-10-30)
  • 官方镜像:hascheksolutions/pictshare:3.7.5(Docker Hub,2026-10-27 推送,digest sha256:9807ef890bfc...)
  • 镜像内置组件:Caddy/FrankenPHP(Web+PHP 8.4.27)、Redis(unix socket 缓存)、ffmpeg(音视频转码)
  • 端口规划:Web 80 → 宿主 8131
  • 数据目录:/opt/pictshare/data(上传内容)、/opt/pictshare/logs(日志)、/opt/pictshare/tmp(临时文件)
  • 独立网络:自定义 bridge 子网 10.89.59.0/24
  • Compose 项目名:pictshare-3.7.5-stack;容器名 pictshare-3.7.5-web

二、镜像选型说明

候选说明结论
hascheksolutions/pictshare:3.7.5Docker Hub 官方镜像,与 GitHub tag v3.7.5 一一对应(另含 3.7/3 滚动 tag 与 latest)首选
ghcr.io/hascheksolutions/pictshare:3GHCR 官方通道,内容同 Docker Hub备选
hascheksolutions/pictshare:latest跟随 master 的滚动 tag不建议生产(版本漂移)
源码构建(仓库自带 docker-compose.yml + Dockerfile)面向开发者的 build 形态,挂载源码热更新本篇不展开

⚠️ 版本选择依据:官方仓库最新稳定 tag 为 v3.7.5(git ls-remote 实查,查询日期 2026-10-30),Docker Hub 对应 3.7.5 tag 于 2026-10-27 推送(digest 与 latest 一致),选 hascheksolutions/pictshare:3.7.5 固定版本部署。本次实测环境直连 Docker Hub 官方源拉取成功,无需降级代理。

镜像底座说明:3.x 镜像基于 dunglas/frankenphp:php8.4-alpine,Caddy 直接内嵌 PHP 解释器并自带 redis/ffmpeg,单容器即可运行完整功能(实测首启日志见 4.3)。

三、前置条件

3.1 宿主端口实查

选取宿主端口前先用 ss 确认目标端口空闲(实测回显):

ss -ltn | awk 'NR>1{print $4}' | grep -oE '[0-9]+$' | sort -un | grep -E '^81[0-9][0-9]$'
8131 8147

实测环境中 8147 已被其他进程占用,本方案选用 8131 作为 Web 宿主端口(若你的机器上 8131 已被占用,按同样方法另选空闲端口即可,注意同步修改 4.1 编排文件与 URL 环境变量)。

3.2 网络子网实查

查看现有 Docker 网络与已占子网(实测回显):

docker network ls --format '{{.Name}}'
bridge
host
none

本次环境中无自定义网络,从 10.89.0.0/16 空闲段选取 59 号槽显式划分子网 10.89.59.0/24(若已有网络占用该段,用 docker network inspect $(docker network ls -q) --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}' 实查后换空闲槽位)。

3.3 目录准备

mkdir -p /opt/pictshare/data /opt/pictshare/logs /opt/pictshare/tmp

三个目录分别对应容器内 /app/public/data(上传内容与元数据)、/app/public/logs(访问/错误日志)、/app/public/tmp(上传临时文件),全部 bind mount 持久化。

四、部署步骤

4.1 Compose 编排文件

在 /opt/pictshare/compose/docker-compose.yml 写入以下内容(完整文件,实测采用):

name: pictshare-3.7.5-stack
services:
  pictshare:
    image: hascheksolutions/pictshare:3.7.5
    container_name: pictshare-3.7.5-web
    environment:
      - URL=http://192.168.146.128:8131/
      - TITLE=PictShare
      - MAX_UPLOAD_SIZE=100
      - ADMIN_PASSWORD=q1w2e3r4
      - LOG_UPLOADER=false
      - REDIS_CACHING=true
    volumes:
      - /opt/pictshare/data:/app/public/data
      - /opt/pictshare/logs:/app/public/logs
      - /opt/pictshare/tmp:/app/public/tmp
    ports:
      - "8131:80"
    networks:
      pictshare-net:
    restart: unless-stopped

networks:
  pictshare-net:
    name: pictshare-3.7.5-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.59.0/24

要点解读:

  • name: pictshare-3.7.5-stack:显式声明 Compose 项目名,避免与主机上其他 compose 栈同名互相干扰;
  • URL=http://192.168.146.128:8131/:必填且必须以斜杠结尾,上传结果 JSON 的 url/delete_url 外链前缀由它决定,改成你自己的服务器 IP 或域名;
  • ADMIN_PASSWORD=q1w2e3r4:管理端 /admin 的访问口令(本文按示例账号规范使用测试口令,生产请换强口令);留空则管理端整体关闭;
  • MAX_UPLOAD_SIZE=100:上传上限(MB),启动脚本会同步改写容器内 php.ini 的 upload_max_filesize/post_max_size,并把 PHP memory_limit 抬到「上传上限 + 30MB」(实测 100M 时 memory_limit=130M);
  • 三个 bind mount 均为官方镜像声明的工作目录,缺省匿名卷会在 docker compose down -v 时丢数据,显式落宿主目录更直观;
  • 网络显式指定名称与子网,不依赖 Docker 自动分配。

4.2 拉起栈并验证

cd /opt/pictshare/compose
docker compose up -d

实测回显:

 Network pictshare-3.7.5-net Created
 Container pictshare-3.7.5-web Creating
 Container pictshare-3.7.5-web Created
 Container pictshare-3.7.5-web Starting
 Container pictshare-3.7.5-web Started

验证监听与状态(实测回显):

docker ps --format '{{.Names}}\t{{.Status}}\t{{.Ports}}'
pictshare-3.7.5-web	Up 6 seconds (health: starting)	443/tcp, 2019/tcp, 443/udp, 0.0.0.0:8131->80/tcp, [::]:8131->80/tcp
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:8131/
HTTP 200

Web 端口返回 200 即部署成功,浏览器访问 http://192.168.146.128:8131/ 进入拖拽上传页。

4.3 首次启动日志判读

docker logs pictshare-3.7.5-web

输出节选(实测首尾):

[i] Redis steps
  [+] Configuring Redis save intervals
Starting Pictshare
[i] Setting uploadsize to 100M
[i] Also changing memory limit of PHP to 130M
[i] Setting file permissions
 [+] Creating config
{"level":"info","ts":1793352543.4909732,"msg":"maxprocs: Leaving GOMAXPROCS=6: CPU quota undefined"}
{"level":"info","ts":1793352543.5100856,"logger":"frankenphp","msg":"FrankenPHP started 🐘","php_version":"8.4.27","total_threads":12,"worker_threads":0,"max_threads":12,"max_requests":0}
{"level":"warn","ts":1793352543.5102944,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":80"}
{"level":"info","ts":1793352543.5103097,"msg":"serving initial configuration"}

判读要点:

  • [i] Setting uploadsize to 100M + memory limit of PHP to 130M:启动脚本按 MAX_UPLOAD_SIZE 改写 php.ini 并抬升内存上限(上限+30MB);
  • [+] Creating config:由环境变量生成 src/inc/config.inc.php,配置变更必须重建容器(docker compose up -d 会检测 env 变化并重建);
  • FrankenPHP started(php_version 8.4.27)+ serving initial configuration:Web 服务就绪;
  • HTTP/2、HTTP/3 因仅监听 HTTP 80 被跳过属正常(HTTPS 需外置反代终结 TLS)。

五、数据持久化说明

宿主路径容器内路径内容
/opt/pictshare/data/app/public/data各 hash 目录(原始文件+变换产物+meta.json)、sha1.csv(去重映射)、uploads.csv(可选上传者 IP 日志)
/opt/pictshare/logs/app/public/logs应用日志(app.log 等,LOG_VIEWS=true 时记录访问)
/opt/pictshare/tmp/app/public/tmp上传/URL 抓取临时文件(处理后自动清理)

首启后实测的数据目录清单(实测回显):

data/
├── mrokk1.png/                  # 一个上传文件一个目录
│   ├── mrokk1.png               # 原始文件
│   ├── 9d4e826c..._mrokk1.png   # URL 变换产物(缩放/滤镜版本)
│   └── meta.json                # mime/大小/sha1/上传时间/IP/删除码
├── sha1.csv                     # sha1 → hash 映射(去重判断依据)
└── naughty.csv                  # 已删除黑名单(v3.7.5 实测始终为空)

⚠️ 注意:Redis 缓存数据在容器内(未持久化),重建容器后缓存自动重建,无需备份;备份只需打包 /opt/pictshare/data,恢复到新机器时同步修改 URL 环境变量为新地址即可。

六、环境变量表

变量实测值说明
URLhttp://192.168.146.128:8131/必填,外链前缀,必须以斜杠结尾
TITLEPictShare页面标题
MAX_UPLOAD_SIZE100上传上限 MB,同步改写 php.ini
ADMIN_PASSWORDq1w2e3r4/admin 管理端口令,空=关闭管理端
LOG_UPLOADERfalsetrue 时把上传者 IP 记入 data/uploads.csv
REDIS_CACHINGtrue内置 Redis URL→文件映射缓存,false 显著变慢

其余全部环境变量(上传口令、子网白名单、S3/FTP 外部存储、加密、内容控制器白名单等)的逐项详解与生效验证见《PictShare 3.7.5 配置参数详解》。

七、部署后功能验证

7.1 图片上传与外链

curl -s -F "file=@/opt/pictshare/test.png" http://127.0.0.1:8131/api/upload
{
    "status": "ok",
    "hash": "mrokk1.png",
    "filetype": "image\/png",
    "url": "http:\/\/192.168.146.128:8131\/mrokk1.png",
    "delete_code": "pj6q3f3i9awmp6kx7hyjt2y5idjnzhda",
    "delete_url": "http:\/\/192.168.146.128:8131\/delete_pj6q3f3i9awmp6kx7hyjt2y5idjnzhda\/mrokk1.png"
}

外链访问验证(实测回显):

curl -sI http://127.0.0.1:8131/mrokk1.png | grep -iE 'HTTP|content-type|cache-control'
HTTP/1.1 200 OK
Cache-Control: public, max-age=31536000
Content-Type: image/png

Cache-Control: max-age=31536000 表明外链可被浏览器/CDN 长缓存(内容寻址保证同 hash 内容不变)。

7.2 URL 变换(缩放)验证

curl -s http://127.0.0.1:8131/300x200/mrokk1.png -o resized.png && file resized.png
resized.png: PNG image data, 300 x 225, 8-bit/color RGB, non-interlaced

原图 800×600,/300x200/ 实际产出 300×225(等比缩放,宽为准),验证 URL 变换管线工作正常。

7.3 视频上传与缩放验证

curl -s -F "file=@/opt/pictshare/test.mp4" http://127.0.0.1:8131/api/upload
{
    "status": "ok",
    "hash": "93i2mx.mp4",
    "filetype": "video\/mp4",
    "url": "http:\/\/192.168.146.128:8131\/93i2mx.mp4",
    "delete_code": "vhrwzjm7udud9w0y0386ba3jhwtle76f",
    "delete_url": "http:\/\/192.168.146.128:8131\/delete_vhrwzjm7udud9w0y0386ba3jhwtle76f\/93i2mx.mp4"
}

MP4 直链返回的是内嵌播放器 HTML 页,真实视频流在 /raw 后缀(实测回显):

curl -sI http://127.0.0.1:8131/93i2mx.mp4/raw | grep -iE 'HTTP|content-type'
HTTP/1.1 200 OK
Content-Type: video/mp4

缩放验证(/320x180/ 生成 320 宽版本,实测产物为 h264 编码 320×180,预览帧 JPEG 320×180):

curl -sI http://127.0.0.1:8131/320x180/93i2mx.mp4/raw | grep -iE 'HTTP|content-type'
HTTP/1.1 200 OK
Content-Type: video/mp4

八、常用运维命令

# 查看实时日志
docker logs -f pictshare-3.7.5-web
# 重启(改环境变量后 compose up -d 会自动重建,无需手动 rm)
docker compose restart
# 升级版本:改 image tag 后重建(data 目录跨版本兼容由官方 v3 系列保证,升级前先备份)
docker compose pull && docker compose up -d
# 进入容器排查(php.ini、config.inc.php、redis-cli)
docker exec -it pictshare-3.7.5-web bash
# 查看实际生效的配置(启动脚本由 env 生成)
docker exec pictshare-3.7.5-web grep -E "define" /app/public/src/inc/config.inc.php

⚠️ 注意:PictShare 的配置不存在「改文件」路径——config.inc.php 每次启动都由环境变量重新生成,手工修改会在下次重启时被覆盖。所有配置变更走 environment: 段 + docker compose up -d 重建。

九、常见问题(FAQ)

Q1:上传大文件报 413 或连接被重置? MAX_UPLOAD_SIZE 只在容器首启时改写 php.ini;若先以默认值启动过再改大,确认容器已被 docker compose up -d 重建(日志出现新的 Setting uploadsize to xxxM 行)。另注意反代(如有 Nginx)的 client_max_body_size 也需同步放大。

Q2:上传成功但返回的 URL 打不开? URL 环境变量写错了(未带尾斜杠、IP/域名与实际访问入口不符)。URL 只是拼接前缀,不影响存储;改对后重建容器即可,历史文件外链会随之指向新前缀。

Q3:删除后的文件 URL 仍返回 200? 分两种情况(实测):删除前从未被访问过的文件 URL 立即 404;删除前被访问过(Redis 缓存了 URL 映射)的文件 URL 继续返回 200 但内容为空壳(1 字节空 body)。监控探活不要以外链 200 作为「文件存在」判据,应改用 GET /api/info/<hash>(实测返回 Hash not found)。

Q4:如何限制谁能上传? 设 UPLOAD_CODE(全局上传口令,API 需带 uploadcode 字段)或 ALLOWED_SUBNET(CIDR 白名单),两者实测均生效,详见《PictShare 3.7.5 配置参数详解》。

十、参考链接

  1. 官方 Docker 文档:https://github.com/HaschekSolutions/PictShare/blob/master/rtfm/DOCKER.md
  2. Docker Hub 镜像页:https://hub.docker.com/r/hascheksolutions/pictshare/tags
  3. 官方仓库:https://github.com/HaschekSolutions/PictShare
  4. 本专栏系列:《PictShare 介绍与选型指南》(https://www.quzuo.net/document/1SbPpyq7F2S5)、《PictShare 3.7.5 配置参数详解》(https://www.quzuo.net/document/K2LlXSHlRiG6)、《PictShare 3.7.5 URL 参数与 HTTP API 详解》(https://www.quzuo.net/document/hepbPtXpdr8g)。