PicoShare 1.5.4 Docker Compose 部署指南

在 Docker 服务器上用 Compose 部署 PicoShare 1.5.4:镜像选型、compose 编排、登录验证、上传与分享实测、数据持久化与常用运维命令,实测通过。

PicoSharePicoShareGolang文件传输文件分享自托管2026/10/31

PicoShare 1.5.4 Docker Compose 部署指南

目标:从零开始在一台 Ubuntu 服务器上用 Docker Compose 部署 PicoShare 1.5.4,完成登录、文件上传、分享链接下载与数据持久化验证。全部命令与回显已在 Ubuntu 22.04 实测通过。

一、环境信息

本文部署过程在以下环境实测:

  • 操作系统:Ubuntu 22.04(x86_64)
  • Docker 版本:29.9.2(Docker Compose v2 插件随 Docker Engine 提供)
  • PicoShare 版本:v1.5.4(官方镜像 mtlynch/picoshare:v1.5.4)
  • 容器内监听端口:4001;宿主机映射端口:8130
  • 数据目录:/opt/picoshare/data(挂载到服务 /data)
  • 实测容器资源占用:内存 4.09MiB,空闲 CPU 0%

二、镜像选型说明

PicoShare 官方只维护一个镜像仓库 mtlynch/picoshare,无 alpine/slim 等变体之分——镜像本身已基于精简基础层构建(二进制 + litestream 共约 45MB)。选型要点:

  • 版本 tag 选择:固定具体版本(如 v1.5.4)而非 latest,便于回滚与复现。注意镜像 tag 从 1.5.3 起带 v 前缀(v1.5.3、v1.5.4),而 1.5.2 及更早版本不带(1.5.2),拉取时需与 Docker Hub 标签逐字一致;
  • v1.5.4 与旧版差异:v1.5.4 的登录口令环境变量为 PS_SHARED_SECRET,且下载链接路由改为 /-<ID> 格式(旧版 /!<ID> 仍兼容保留);
  • 镜像内置组件:/app/litestream(S3 兼容数据库备份工具)与 /app/docker-entrypoint(入口脚本,按 LITESTREAM_BUCKET 是否设置决定是否启用备份)。

本文实测拉取(官方源直连可用,未发生降级):

docker pull mtlynch/picoshare:v1.5.4
479840ee4f60: Pull complete
d94c665ce234: Pull complete
Digest: sha256:053fee7cbdc64894e924733d5405158a9baadbecd231bfe97ae69d16fd2c2639
Status: Downloaded newer image for mtlynch/picoshare:v1.5.4
docker.io/mtlynch/picoshare:v1.5.4

💡 技术拓展:文件分享服务的容器镜像来源有两类——官方自建镜像(本文所用)与社区封装镜像(如 linuxserver.io 系列)。官方镜像随源码同源构建、发布节奏一致,但通常不带统一的环境变量再封装;社区镜像常集成更多配置项,但存在版本滞后与维护断档风险。生产环境建议优先官方镜像并固定版本 tag。

三、前置条件

  1. 服务器已安装 Docker Engine 20.10+ 与 Compose v2 插件:
docker version --format '{{.Server.Version}}'
29.9.2
  1. 目标端口空闲。本文预分配宿主机端口 8130,部署前实测确认未被占用:
ss -ltnp | grep :8130 || echo "8130 空闲"
8130 空闲
  1. 数据目录已规划(本文示例为 /opt/picoshare/data)。

四、部署步骤

4.1 编写 docker-compose.yml

创建项目目录并写入编排文件:

mkdir -p /opt/picoshare/compose /opt/picoshare/data
cat > /opt/picoshare/compose/docker-compose.yml <<'EOF'
name: picoshare-1.5.4-stack

services:
  picoshare:
    image: mtlynch/picoshare:v1.5.4
    container_name: picoshare-1.5.4-app
    environment:
      - PS_SHARED_SECRET=q1w2e3r4
    ports:
      - "8130:4001"
    volumes:
      - /opt/picoshare/data:/data
    networks:
      - picoshare-net
    restart: unless-stopped

networks:
  picoshare-net:
    name: picoshare-1.5.4-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.58.0/24
EOF

配置逐项说明:

  • name: picoshare-1.5.4-stack:Compose 项目名,决定容器/网络的归属分组;
  • container_name: picoshare-1.5.4-app:显式容器名,便于 docker logs/docker exec 直达;
  • PS_SHARED_SECRET=q1w2e3r4:管理员登录口令(v1.5.4 必填项,缺失时服务无法启动);
  • ports "8130:4001":宿主机 8130 → 容器 4001(4001 为 PicoShare 默认监听端口);
  • volumes:宿主机数据目录挂载到容器 /data,数据库文件 store.db 落在宿主机;
  • networks:自定义 bridge 网络,显式指定网段 10.89.58.0/24,避免与宿主机上其他 Compose 项目的默认网段冲突;
  • restart: unless-stopped:异常退出或宿主机重启后自动拉起(手动 stop 的除外)。

4.2 启动服务

cd /opt/picoshare/compose && docker compose up -d
 Network picoshare-1.5.4-net Created
 Container picoshare-1.5.4-app Created
 Container picoshare-1.5.4-app Started

4.3 验证容器与日志

docker compose ps
NAME                  IMAGE                      COMMAND                  SERVICE     CREATED         STATUS         PORTS
picoshare-1.5.4-app   mtlynch/picoshare:v1.5.4   "/app/docker-entrypo…"   picoshare   4 seconds ago   Up 4 seconds   0.0.0.0:8130->4001/tcp, [::]:8130->4001/tcp

日志确认监听就绪(实测节选):

docker logs picoshare-1.5.4-app 2>&1 | tail -3
Starting without litestream
2026/10/30 09:29:10 /app/cmd/picoshare/main.go:27: starting picoshare server
2026/10/30 09:29:10 /app/store/sqlite/sqlite.go:37: reading DB from /data/store.db
2026/10/30 09:29:10 /app/cmd/picoshare/main.go:70: listening on 4001

⚠️ 注意(实测踩坑):若误用旧教程的 PSK 变量名,容器会进入反复重启状态,日志报错 failed to read shared secret: PS_SHARED_SECRET or PS_SHARED_SECRET_FILE must be set。v1.5.4 只认 PS_SHARED_SECRET(或 PS_SHARED_SECRET_FILE 指向的口令文件)。

4.4 首页可达验证

curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8130/
200

4.5 登录、上传与分享实测

登录获取会话 Cookie(/api/auth 端点,请求体字段为 sharedSecretKey):

curl -si -X POST http://localhost:8130/api/auth -H 'Content-Type: application/json' \
  -d '{"sharedSecretKey":"q1w2e3r4"}' | head -3
HTTP/1.1 200 OK
Set-Cookie: sharedSecret=a7XY9QIgm2mimIUtd0ZWY8sETVBgF/ERlYeATvYexqw=; Path=/; Max-Age=2592000; HttpOnly; SameSite=Strict

带 Cookie 上传测试文件(expiration 为必填查询参数,RFC3339 格式且至少晚于当前 1 小时):

echo "hello picoshare" > /tmp/hello.txt
curl -s -b "sharedSecret=a7XY9QIgm2mimIUtd0ZWY8sETVBgF/ERlYeATvYexqw=" \
  -F "file=@/tmp/hello.txt" "http://localhost:8130/api/entry?expiration=2026-11-06T00:00:00Z"
{"id":"hKXXo7sX75"}

用返回的 ID 构造分享链接,以匿名身份(不带 Cookie)验证下载:

curl -si http://localhost:8130/-hKXXo7sX75 | head -8
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Disposition: filename="hello.txt"
Content-Length: 27
Content-Security-Policy: sandbox
Content-Type: text/plain

浏览器访问 http://<服务器IP>:8130/,输入口令 q1w2e3r4 登录后即可在 Web 界面上传与复制分享链接。API 与页面的完整用法见 《PicoShare 1.5.4 API 使用详解》。

五、数据持久化说明

PicoShare 把文件内容与全部元数据都存进单个 SQLite 数据库 /data/store.db(容器内路径),因此持久化只需保住这一个目录。实测数据目录内容:

ls -la /opt/picoshare/data/
-rw-r--r-- 1 root root 7921664 Oct 30 17:33 store.db
-rw-r--r-- 1 root root   32768 Oct 30 17:34 store.db-shm
-rw-r--r-- 1 root root 4429032 Oct 30 17:34 store.db-wal

重启容器验证持久化(实测:重启后文件仍可下载):

docker restart picoshare-1.5.4-app >/dev/null && sleep 3
curl -s -o /dev/null -w "重启后下载 -> %{http_code}\n" http://localhost:8130/-hKXXo7sX75
重启后下载 -> 200

💡 技术拓展:SQLite 落盘会产生 store.db(主库)、store.db-wal(预写日志)、store.db-shm(共享内存索引)三个文件。WAL 模式允许读写并发,掉电时主库 + WAL 联合恢复。备份时三者必须一起复制(或使用 Litestream/VACUUM INTO),只拷主库会丢失 WAL 中未合并的数据。

需要异地容灾时,启用镜像内置的 Litestream 复制(S3 兼容存储),在 environment 中追加:

    environment:
      - PS_SHARED_SECRET=q1w2e3r4
      - LITESTREAM_BUCKET=my-backup-bucket
      - LITESTREAM_ENDPOINT=s3.example.com
      - LITESTREAM_ACCESS_KEY_ID=${PICO_AK}
      - LITESTREAM_SECRET_ACCESS_KEY=${PICO_SK}
      - LITESTREAM_RETENTION=72h

启用后入口脚本改由 litestream replicate -exec 拉起主进程,WAL 准实时复制到对象存储(快照间隔 24h,保留期默认 72h),并在容器启动时自动执行 litestream restore 恢复已有备份。系统级真实密钥建议用 PS_SHARED_SECRET_FILE 挂载口令文件注入,而非明文写在 compose 中;PICO_AK/PICO_SK 为备份桶密钥,用 shell 环境变量注入(先 export PICO_AK=实际密钥、export PICO_SK=实际密钥,再执行编排重建),避免明文进入编排文件历史。

六、环境变量表

v1.5.4 全部环境变量(来源:官方 README 与源码逐项核对):

环境变量作用默认值必填
PS_SHARED_SECRET管理员登录口令(与 PS_SHARED_SECRET_FILE 二选一)无是(二选一)
PS_SHARED_SECRET_FILE口令文件路径(Docker secrets 场景用)无否
PORTHTTP 监听端口4001否
PS_BEHIND_PROXY置为 true 时按反向代理模式处理日志与生成的链接协议未设置否
LITESTREAM_BUCKETS3 兼容备份桶名;非空即启用 Litestream未设置(不启用)否
LITESTREAM_ENDPOINTS3 兼容存储 endpoint未设置否
LITESTREAM_ACCESS_KEY_ID备份桶访问密钥 ID未设置启用 Litestream 时必填
LITESTREAM_SECRET_ACCESS_KEY备份桶秘密密钥未设置启用 Litestream 时必填
LITESTREAM_RETENTION备份快照与 WAL 保留时长72h否

另有一个启动参数(非环境变量)-db:SQLite 数据库路径,官方镜像默认 data/store.db,Docker 场景由入口脚本固定为 /data/store.db。

七、配置参数说明

PicoShare 没有 YAML/INI 配置文件——所有配置只通过环境变量与启动参数下发,上文两张表即全部可配置项。运行期可在 Web 界面 Settings 页调整「默认文件存活期」(对应 API PUT /api/settings,取值 1~3650 天或永不过期),该值存入数据库、随卷持久化。反向代理场景在 nginx 中把 proxy_pass http://127.0.0.1:8130; 指向本服务,并给容器追加 PS_BEHIND_PROXY=true 即可。

八、配置文件挂载

除数据卷外,PicoShare 唯一可能的文件挂载是口令文件(替代 PS_SHARED_SECRET 明文变量)与Litestream 配置覆盖:

  • 口令文件方式(推荐生产使用):
    environment:
      - PS_SHARED_SECRET_FILE=/run/secrets/picoshare_psk
    secrets:
      - picoshare_psk

secrets:
  picoshare_psk:
    file: ./picoshare_psk.txt
  • Litestream 的高级配置(快照间隔、压缩等)内置于镜像的 litestream.yml,通过 LITESTREAM_* 环境变量注入即可覆盖绝大多数需求;如需彻底自定义,可挂载自己的 yml 并绕过官方入口脚本直接运行 /app/litestream replicate -exec "/app/picoshare -db /data/store.db"。

九、等价 docker run

与上文 Compose 完全等价的单命令启动方式:

docker run -d \
  --name picoshare-1.5.4-app \
  --network picoshare-1.5.4-net \
  -p 8130:4001 \
  -v /opt/picoshare/data:/data \
  -e PS_SHARED_SECRET=q1w2e3r4 \
  --restart unless-stopped \
  mtlynch/picoshare:v1.5.4

参数与 Compose 版逐项对应:-p 端口映射、-v 数据卷、-e 登录口令、--restart 重启策略。日常使用仍建议 Compose 编排,便于升级与网络管理。

十、常用运维命令

以下命令均在实测环境验证(项目目录:/opt/picoshare/compose):

docker compose ps                    # 查看容器状态
docker logs -f picoshare-1.5.4-app   # 跟踪服务日志
docker stats --no-stream picoshare-1.5.4-app   # 资源占用
docker compose restart               # 重启服务
docker compose down                  # 停止并移除容器与网络(保留数据卷/目录)
docker compose down -v               # 连同命名卷一起移除(本文用宿主机目录挂载,数据不受影响)

docker stats 实测回显:

NAME                  CPU %   MEM USAGE / LIMIT   NET I/O         BLOCK I/O   PIDS
picoshare-1.5.4-app   0.00%   4.09MiB / 15.57GiB   1.2kB / 1.6kB   -- / --     5

版本升级:修改 compose 中镜像 tag(如 v1.5.4 → 新版本)后执行 docker compose up -d,容器以新镜像重建,数据卷不动即完成原地升级;回滚同理改回旧 tag 重建即可。

十一、常见问题

11.1 容器反复重启,日志报 PS_SHARED_SECRET 错误

现象:docker ps 显示 Restarting (1),日志含 failed to read shared secret: PS_SHARED_SECRET or PS_SHARED_SECRET_FILE must be set。

原因:v1.5.4 起登录口令变量为 PS_SHARED_SECRET,旧文档中的 PSK 变量已不被识别。

解决:compose 中改为 PS_SHARED_SECRET=<口令> 后 docker compose up -d 重建。

11.2 上传时报 Invalid expiration URL parameter

原因:expiration 参数不是 RFC3339 格式,或指定的时间距当前不足 1 小时(实测报错原文:Invalid expiration URL parameter: expire time must be at least one hour in the future)。

解决:使用 RFC3339 格式(如 2026-11-06T00:00:00Z),且至少晚于当前 1 小时。注意 v1.5.4 上传 API 的 expiration 是必填参数,省略或传 Never 都会报同样的 400 错误(实测核对过),脚本要近似「不过期」时传一个远期时间即可。

11.3 分享链接 404

排查顺序:确认 URL 格式为 /-<ID>(如 /-hKXXo7sX75,减号开头);旧版 /<ID> 与 /<ID>/<filename> 形式的链接在 v1.5.4 已不再注册路由,/!<ID> 为兼容格式仍可用;再确认文件未被删除或未到过期时间(过期文件由调度器每 7 小时清理一次)。

11.4 端口冲突

宿主机 8130 被占用时,修改 compose 的 ports 左侧端口即可(容器内 4001 不必改动)。检查占用命令:ss -ltnp | grep :8130。

十二、参考链接