copyparty 容器化部署与镜像构建:Docker/Podman 实战全指南
【免费下载链接】copypartyPortable file server with accelerated resumable uploads, dedup, WebDAV, SFTP, FTP, TFTP, zeroconf, media indexer, thumbnails++ all in one file项目地址: https://gitcode.com/GitHub_Trending/co/copyparty
copyparty 是一个把加速断点续传上传、去重、WebDAV、SFTP、FTP、媒体索引与缩略图等功能集于一身的便携式文件服务器,而本指南围绕其官方容器镜像 scripts/docker/README.md 展开:从一条docker run快速启动、五个镜像版本(min/im/ac/iv/dj)的选型、/cfg配置目录玩法,到 FTP 穿透、mimalloc 提速、音乐 BPM/调性检测,直至基于 make.sh 的完整多架构自建流程与镜像二开技巧。读完你既能快速跑起一个可用的容器实例,也能按需定制属于自己的镜像。
容器镜像的获取渠道
copyparty 官方镜像以“edition 名”区分,发布在以下两个 registry:
- Docker Hub:
docker.io/copyparty/*(组织名为copyparty) - GitHub Container Registry:
ghcr.io/9001/copyparty-*
两者内容一致,例如推荐版ac在 Docker Hub 写为copyparty/ac,在 ghcr 写为ghcr.io/9001/copyparty-ac;后续docker run、FROM指令均可按需替换。仓库根目录的 README.md 与 setup.py、pyproject.toml 同时提供了非容器形态(PyPI 模块、sfx 单文件、源码运行)的安装说明,本指南只聚焦容器形态。
快速开始:一条命令拉起服务
getting started给出的最简启动命令是:
docker run --rm -it -u 1000 -p 3923:3923 -v /mnt/nas:/w -v $PWD/cfgdir:/cfg copyparty/ac逐项拆解这条命令的含义(也即后续所有配置的基础):
-u 1000:以 UID/GID 1000 运行,避免容器内 root 与宿主机权限纠缠;如果你使用的是 rootless podman,需要去掉-u 1000。-p 3923:3923:把容器内 3923 端口映射到宿主机。copyparty 的默认监听端口就是 3923。-v /mnt/nas:/w:/w是容器内默认被共享出去的目录,把任意一个或多个想分享的宿主机目录挂载到它下面即可。-v $PWD/cfgdir:/cfg:/cfg是可选的配置目录,里面可以放零个或多个*.conf配置文件,启动时会被自动加载。copyparty/ac:文档推荐的镜像版本,详见下文“版本选型”。
两个易踩的坑也一并说明:
- SELinux 环境:需要给所有
-v参数追加:z,例如-v /mnt/nas:/w:z。 - Podman 用户:如果使用 rootless podman,按上文去掉
-u 1000即可。
不想手敲命令的话,仓库里还附带了一份 podman-compatible 的编排文件 docs/examples/docker/basic-docker-compose/docker-compose.yml,使用方式为docker-compose up(可能需先systemctl enable --now podman.socket之类的准备)。基于 Portainer 的图形化部署步骤见 docs/examples/docker/portainer.md。
容器内的默认行为与配置方式
与 sfx/PyPI 一致的默认配置
官方镜像刻意保持了和sfx 单文件版、PyPI 模块版相同的默认行为:监听 3923 端口,并把“当前目录”(即容器内的/w)以任何人可读写的方式分享出去。
这一默认行为在镜像的构建脚本 scripts/docker/innvikler.sh 里写得很直白——它生成的初始配置initcfg内容为:
[global] chdir: /w no-crt % /cfg其中chdir: /w把工作目录切到共享卷,no-crt关闭默认自签证书生成,% /cfg则是把/cfg下所有*.conf文件 include 进来。随后cpp.sh负责真正拉起进程:若设置了DI_PREPARTY环境变量则先执行预处理脚本,最后exec /usr/bin/python3 -m copyparty "$@"。也就是说,向docker run传入的任何额外参数都会被直接透传给 copyparty 本体,因此“用参数配置”和“用文件配置”是并行的两条路径。
推荐的配置方式:挂载 /cfg 目录
文档明确推荐的做法是把整个配置文件夹挂载为/cfg,文件夹里放一个或多个配置文件:
-v /your/config/folder:/cfg需要遵守的规则:
- 配置文件必须以
something.conf命名,才会被% /cfg指令拾取。 - 你也可以直接给 docker 命令追加命令行参数,作用等价(例如把全局配置写进
-p 3939、-e2dsa等)。 - 官方 docs/example.conf 是更完整的参数示例,但它不是为容器准备的,直接套用会路径错位——比如文件系统路径应为容器内的
/w/something而非/home/ed/Music。
容器版推荐的最小示例见 docs/examples/docker/basic-docker-compose/copyparty.conf,其中演示了容器场景下的关键写法:
[global] e2dsa # 启用文件系统索引与扫描 e2ts # 启用多媒体索引 ansi # 日志着色 [accounts] ed: wark # 用户名: 密码 [/] # 在 web 根 "/" 创建卷 /w # 共享容器内的 /w 数据卷 accs: rw: * # 所有人都可读写 rwmda: ed # 用户 ed 额外拥有 move/delete/admin flags: e2ds # 仅对该卷启用文件系统扫描镜像的构建骨架(了解镜像行为的关键)
从 scripts/docker/Dockerfile.ac 可以看到容器化配置的另一面:镜像统一设置ENV XDG_CONFIG_HOME=/cfg、WORKDIR /state、EXPOSE 3923,入口统一为/bin/ash /z/cpp.sh -c /z/initcfg。唯一例外是 Dockerfile.min,它在入口处追加了--no-thumb参数以彻底关闭缩略图能力。也就是说,无论哪个版本,其启动序列都是“先按 initcfg 初始化默认全局配置 → include/cfg下所有*.conf→ 透传剩余命令行参数启动 copyparty”。
版本选型 editions
五个官方版本的能力梯度
官方镜像按“内置依赖多寡”分成五个 edition(下表尺寸为安装后体积,含 gzip 压缩体积):
| 镜像 | 体积(安装后 / gzip) | 相对上一版新增能力 |
|---|---|---|
min | 57 MiB / 20 MiB gz | 只有 copyparty 本体,无缩略图/媒体标签/音频转码 |
im | 70 MiB / 25 MiB gz | 用Pillow生成图片缩略图、用Mutagen解析媒体标签 |
ac | 163 MiB / 56 MiB gz | 在im之上加FFmpeg:音视频缩略图、音频转码、更完整的标签解析 |
iv | 211 MiB / 73 MiB gz | 在ac之上加libvips:支持更多缩略图格式 |
dj | 309 MiB / 104 MiB gz | 在iv之上加beatroot/keyfinder:检测音乐调性与 BPM |
仓库源码与上述能力一一对应:Dockerfile.im 的依赖列表里有py3-pillow py3-mutagen;Dockerfile.ac 追加了ADD_PKG=ffmpeg(其自定义 ffmpeg 构建细节见 scripts/docker/base/README.md);Dockerfile.iv 引入pyvips与vips-jxl vips-poppler vips-magick等;Dockerfile.dj 则安装了keyfinder-cli、Vamp SDK、py3-numpy fftw libsndfile并把标签脚本拷到镜像的/mtag/目录。
选型建议
ac是官方推荐的默认选择,理由是iv和dj额外提供的能力在多数场景下很少被用到。
也就是说:只想当纯文件服务器用min;需要常见图片/音频元数据能力用im或ac;处理 RAW、JPEG-XL、PDF 等冷门缩略图格式再考虑iv;做音乐资料库管理才需要dj的调性/BPM 检测。
各 CPU 架构可用的版本矩阵
官方镜像按 manifest list 发布多架构,具体可用组合如下:
| 架构 | 可运行版本 |
|---|---|
x86(i386 / 386) | min、im、ac、iv、dj |
x86_64(x64 / amd64) | min、im、ac、iv、dj |
AArch64(arm64/v8) | min、im、ac、iv、dj |
arm32(arm/v7) | min、im、ac |
ppc64le(PowerPC) | min、im、ac |
s390x(IBM 大型机) | min、im、ac |
该表与 make.sh 中声明的sarchs="386 amd64 arm/v7 arm64/v8 ppc64le s390x"及“已知不兼容”列表(iv/dj的 ppc64le/s390x/arm 组合)完全吻合——低配架构受限于依赖生态,拿不到iv和dj。
注意:
djd、djf、djff、dju是尚未完成的实验版本,未在任何地方发布,对应 Dockerfile 虽存在(见 scripts/docker)但不应在生产使用。
在 dj 版本中检测 BPM 与音乐调性
dj镜像随附keyfinder与beatroot,可在“多媒体索引”阶段为音频文件生成.bpm与key标签。有三种开启方式:
方式一:全局开启(写入/cfg下的某个*.conf):
[global] e2dsa, e2ts # 启用文件系统索引和多媒体索引 mtp: .bpm=f,t30,/mtag/audio-bpm.py # 约需 10 秒/文件 mtp: key=f,t190,/mtag/audio-key.py # 约需 50 秒/文件方式二:仅对某个卷开启:
[/music] # 分享名 / URL 路径 music # /w 数据卷内的文件系统路径 flags: e2dsa, e2ts mtp: .bpm=f,t30,/mtag/audio-bpm.py mtp: key=f,t190,/mtag/audio-key.py方式三:命令行参数:
-e2dsa -e2ts -mtp .bpm=f,t30,/mtag/audio-bpm.py -mtp key=f,t190,/mtag/audio-key.py这里的mtp(multiprocessing tag)参数结构为标签名=写入位置,超时秒数,处理脚本路径,其中/mtag/audio-bpm.py与/mtag/audio-key.py正是 Dockerfile.dj 在构建期从仓库bin/mtag拷贝进镜像的分析脚本。e2ts(multimedia indexing)会触发标签提取流程,e2dsa保证文件系统被持续扫描以发现新文件。
Docker 专项优化建议
把 .hist 状态目录挪进 /cfg
copyparty 默认会在每个共享卷顶部创建.hist目录,用来存放文件系统索引、缩略图等缓存。出于性能与整洁考虑,容器场景更建议把这些状态挪到配置目录里统一管理。在copyparty.conf的[global]段加入一行即可:
hist: /cfg/hists/这样卷内不会被索引文件“污染”,且/cfg通常是独立挂载、更利于备份。
用 mimalloc 提升性能(可选,慎用)
如果希望更快,且能接受内存占用翻倍,可以启用官方内置的 mimalloc 分配器(Dockerfile.ac等均安装了mimalloc2包)。注意官方注释maybe buggy(可能有 bug):
-e LD_PRELOAD=/usr/lib/libmimalloc-secure.so.2:下载为 zip 的打包速度约3x、文件系统索引约1.5x;-e LD_PRELOAD=/usr/lib/libmimalloc-insecure.so.2:在 secure 版基础上再快约 10%,但更易被利用未来的漏洞。
完整示例:
podman run --rm -it -p 3923:3923 -v "$PWD:/w:z" -e LD_PRELOAD=/usr/lib/libmimalloc-secure.so.2 copyparty/ac -v /w::r在容器中开启 FTP 服务
FTP 是一个“奇怪”的协议,一旦套上 Docker 的端口隔离就更麻烦。开启它需要在copyparty.conf的[global]段写三条配置:
ftp: 3921 # 启用 FTP 服务,监听 3921 端口 ftp-nat: 127.0.0.1 # 必须替换为服务器真实外网 IP ftp-pr: 12000-12099 # 限制 passive 模式的端口范围ftp:服务开关与监听端口。ftp-nat:客户端只能连到该 IP,即使服务器有多 IP 也只会拿到这个地址;因此要填服务器真实的外网 IP(示例里的127.0.0.1必须替换)。如果你用 host 网络运行容器,不要加ftp-nat。ftp-pr:把 passive 模式(数据连接)限制在12000-12099区间,最多支持约 100 个并发文件传输。
最后别忘了把这段端口范围(12000-12099)暴露到外网——Dockerfile里默认只EXPOSE 3923,数据端口区间需要由你自行在 docker/compose 中放行。
常见问题 FAQ
Q:在 Debian 12 上以 rootless 方式启动容器报错failed to register layer: lsetxattr user.overlay.impure /etc: operation not supported,怎么办?
A:Docker 在 Debian 上的默认 rootless 配置使用了 overlay2 存储驱动,而这个驱动在 rootless 下无法工作。可选方案:一是换用 Podman(文档推荐的好选择);二是把 Docker 的存储驱动改成fuse-overlayfs。
官方声明该 FAQ 为尽力而为的最佳实践,不保证完全正确。
自建镜像:从零构建官方多架构镜像
一键脚本 make.sh
仓库自带的 scripts/docker/make.sh 负责多架构矩阵构建。基本流程一句话就能概括:
./make.sh hclean pull img push命令拆解(每个单词是独立的动作,顺序即流程):
hclean:清理本地的旧构建镜像;pull:为各架构拉取alpine:latest基础镜像并打本地 tag(make.sh会把 alpine 镜像按架构 re-tag,如alpine-amd64);img:解包 sfx 并并发构建所有版本 × 所有架构;push:把构建好的 manifest list 推到 Docker Hub 与 ghcr。
构建细节非常“工程化”,值得了解的点:
- 前置依赖:脚本会校验
awk jq podman python3 tar wget,缺少任何一个都会直接退出;并且拒绝以 root 运行(dont root)。 - 构建素材来源:默认从 GitHub Releases 下载最新的
copyparty-sfx.py到../../dist/(若已存在则复用),除非你已按 docs/devnotes.md 从源码完整构建过 sfx。构建期还会从仓库收集bin/mtag标签脚本与base/下的自定义 ffmpeg APK、zlib-ng wheel 等(细节见 scripts/docker/Makefile 与 scripts/docker/base/README.md)。 - AAC 解码自检:
img阶段会先用 ffmpeg 生成若干 AAC 测试样本,再在镜像内逐个转码验证——这是为了确保镜像内置的“裁剪版” ffmpeg(见 docs/bad-codecs.md)行为符合预期。 - 架构策略:amd64/arm64 等大架构全量构建,
iv/dj的ppc64le/s390x/arm组合按已知不兼容跳过;aarch64 宿主机还会通过 binfmt_misc 注册 qemu-arm 以便交叉构建 arm32。 - OOM 友好的并行调度:构建并发数受
nproc限制,arm 系任务优先调度。 - 推送:Docker Hub 与 ghcr 的推送并行执行,各打
:latest/:beta/:版本号标签。推送前需先登录:podman login docker.io以及podman login ghcr.io -u <用户名>。
详细的排障与逐步骤说明在 scripts/docker/devnotes.md。
被弃用的 make 备选方案
如果不想用make.sh,仓库根目录还有一个旧式 Makefile,运行make亦可构建,但它使用 docker 而非 podman、只构建 x86_64,且各目标(min/im/ac/iv/dj)对应不同的Dockerfile.*。作者注明这是 deprecated alternative。
在 Alpine 宿主机上构建
scripts/docker/devnotes.md 提供了 Alpine 专属准备流程:安装podman、启用cgroups、把存储驱动切到btrfs、配置/etc/subuid与/etc/subgid、安装 qemu 全家桶并启用qemu-binfmt——这样才能在 x86 宿主机上交叉构建 arm/s390x/ppc64le 等架构。
给官方镜像“打补丁”:两种二开姿势
方式一:基于官方镜像重新构建(推荐)
如果你的诉求只是“往官方镜像里加一个包”,不必把整个多架构矩阵重新跑一遍。做法是新建目录与 Dockerfile:
mkdir customparty cd customparty nano Dockerfile例如想装 Python 包requests(在 Alpine 里对应的包名是py3-requests),Dockerfile 内容只需两行:
FROM docker.io/copyparty/ac:latest RUN apk add --no-cache py3-requests然后拉取基础镜像并构建:
docker pull docker.io/copyparty/ac:latest docker build -t customparty .之后localhost/customparty:latest就是带了你定制内容的copyparty/ac。
重要提醒:min镜像为了极致瘦身做过大量裁剪(见 innvikler.sh 中删除 libstdc++、readline、asyncio 等一大串“高尔夫”操作),结构很脆,不适合在上面二次定制;请以im/ac/iv/dj为基础。另外,每次想升级 copyparty 版本时,都必须回到这个目录重新执行pull+build,否则你的定制层仍停留在旧基础镜像上。
方式二:启动时即时改装(modding on the fly)
如果连构建镜像的条件都没有,还可以让改动在“镜像启动、copyparty 运行前”的间隙生效。原理在 Dockerfile.ac 的入口/z/cpp.sh中可见:如果设置了环境变量DI_PREPARTY,容器会先执行/cfg/$DI_PREPARTY(要求只能传文件名、不能含路径分隔符),成功后才拉起 copyparty。
操作步骤:在映射到/cfg的卷里放一个 shell 脚本(例如strikk-og-binders.sh),并保证容器始终以环境变量DI_PREPARTY=strikk-og-binders.sh启动。docker-compose 用户可参考 docs/examples/docker/basic-docker-compose/docker-compose.yml 里的环境变量写法。
devnotes.md特别提醒:如果用它来做“每次启动都装包”这种事,务必做本地缓存,避免每次重启都去请求 Alpine 服务器,给社区镜像源造成不必要的压力。以下是带缓存的示例(以安装exiftool与py3-requests为例):
set -e # 任一步出错立即崩溃退出 #set -x # 调试时取消注释(开启命令日志) # 要安装的包 pkgs="exiftool py3-requests" # 镜像比缓存新 → 清掉缓存 [ /z/initcfg -nt /cfg/apks/t ] && rm -rf /cfg/apks # 缓存里不是这批包 → 清掉缓存 grep -qF "$pkgs" /cfg/apks/t || rm -rf /cfg/apks # 已有缓存 → 直接离线安装(去掉 -q 可看详细输出) [ -e /cfg/apks ] && exec apk add -q --progress=no /cfg/apks/*.apk # 无缓存 → 下载 + 缓存 + 安装 mkdir /cfg/apks apk add --cache-predownload --cache-dir /cfg/apks --progress=no $pkgs echo "$pkgs" >/cfg/apks/t touch -r /z/initcfg /cfg/apks/t缓存判定技巧:以容器内镜像自带的/z/initcfg文件时间戳作为“镜像新旧”基准,配合包名清单文件来触发缓存失效。安全性上可以放心,因为 Alpine 的.apk包是签名的,无法被篡改。同样地,min镜像结构脆弱,不建议用这种方式改装,请选im/ac/iv/dj。
小结
容器化的 copyparty 把“一个文件搞定文件分享”的哲学延续到了镜像分发上:min到dj五个版本对应从纯 HTTP 分享到完整媒体资料库的五档能力,/w+/cfg两个挂载点即覆盖“分享什么”与“怎么配置”两件事。若需更深度的定制,既可以走make.sh的全量多架构自建,也可以基于ac做一两行的增量镜像,甚至用DI_PREPARTY实现不落地的即时改装。更多配置参数请查阅 docs/example.conf,镜像构建细节可继续研读 scripts/docker/devnotes.md 与 scripts/docker/make.sh。
【免费下载链接】copypartyPortable file server with accelerated resumable uploads, dedup, WebDAV, SFTP, FTP, TFTP, zeroconf, media indexer, thumbnails++ all in one file项目地址: https://gitcode.com/GitHub_Trending/co/copyparty
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考