PictShare 3.7.5 Docker Compose 部署指南
在 Linux 服务器上用 Docker Compose 部署 PictShare 3.7.5,覆盖镜像选型、端口规划、首启验证、上传实测与数据持久化全流程。
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 推送,digestsha256: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.5 | Docker Hub 官方镜像,与 GitHub tag v3.7.5 一一对应(另含 3.7/3 滚动 tag 与 latest) | 首选 |
ghcr.io/hascheksolutions/pictshare:3 | GHCR 官方通道,内容同 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.5tag 于 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,并把 PHPmemory_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环境变量为新地址即可。
六、环境变量表
| 变量 | 实测值 | 说明 |
|---|---|---|
| URL | http://192.168.146.128:8131/ | 必填,外链前缀,必须以斜杠结尾 |
| TITLE | PictShare | 页面标题 |
| MAX_UPLOAD_SIZE | 100 | 上传上限 MB,同步改写 php.ini |
| ADMIN_PASSWORD | q1w2e3r4 | /admin 管理端口令,空=关闭管理端 |
| LOG_UPLOADER | false | true 时把上传者 IP 记入 data/uploads.csv |
| REDIS_CACHING | true | 内置 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 配置参数详解》。
十、参考链接
- 官方 Docker 文档:https://github.com/HaschekSolutions/PictShare/blob/master/rtfm/DOCKER.md
- Docker Hub 镜像页:https://hub.docker.com/r/hascheksolutions/pictshare/tags
- 官方仓库:https://github.com/HaschekSolutions/PictShare
- 本专栏系列:《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)。