rclone-sync 是一个 Docker 化的 rclone 任务运行器。它用环境变量或 YAML 配置,把一个存储位置的数据复制、镜像、归档或清理到另一个位置。
常见用途:
.tmp、.part、.bak 等后缀文件。底层传输全部交给 rclone。镜像内置 Python runner,只用于配置解析、安全校验、调度和通知。
把示例 env 复制成真实 env:
cp rclone-sync.env.example rclone-sync.env
vim rclone-sync.env
先用 dry-run 启动:
docker run --rm \
--name rclone-sync \
--env-file ./rclone-sync.env \
-v "$PWD/logs:/logs" \
-v "$PWD/state:/state" \
your-dockerhub-user/rclone-sync:latest
确认日志没问题后,再常驻运行:
docker run -d \
--name rclone-sync \
--restart unless-stopped \
--env-file ./rclone-sync.env \
-v "$PWD/logs:/logs" \
-v "$PWD/state:/state" \
your-dockerhub-user/rclone-sync:latest
发布到 Docker Hub 后,把 your-dockerhub-user/rclone-sync:latest 换成你的真实镜像名。
默认 docker-compose.yml 面向 Docker Hub 用户,不做本地 build:
services:
rclone-sync:
image: ${RCLONE_SYNC_IMAGE:-your-dockerhub-user/rclone-sync:latest}
restart: unless-stopped
env_file:
- ${RCLONE_SYNC_ENV_FILE:-./rclone-sync.env}
volumes:
- ./logs:/logs
- ./state:/state
- ./filters:/filters:ro
使用:
cp rclone-sync.env.example rclone-sync.env
vim rclone-sync.env
RCLONE_SYNC_IMAGE=your-dockerhub-user/rclone-sync:latest docker compose up -d
本地开发构建用 override 文件:
RCLONE_SYNC_ENV_FILE=./tmp/real-b2-to-google-drive.env \
RCLONE_SYNC_NETWORK_MODE=host \
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build
RCLONE_SYNC_ENV_FILE 可以指定任意 env 文件。默认是 ./rclone-sync.env。
RCLONE_SYNC_NETWORK_MODE=host 只在需要容器访问宿主机 127.0.0.1 代理时使用。默认 bridge 隔离更好。bridge 模式里,容器内的 127.0.0.1 是容器自己,不是宿主机。
rclone-sync.env.example 默认是 dry-run,不会真的移动或删除:
TZ=Asia/Shanghai
RCLONE_SYNC_MODE=archive
RCLONE_SYNC_DRY_RUN=true
# RCLONE_SYNC_ALLOW_DESTRUCTIVE=true
RCLONE_SYNC_OLDER_THAN=3M
RCLONE_SYNC_EXCLUDE_EXTENSIONS=.tmp,.part,.bak
RCLONE_SYNC_DIRECTORIES=.
RCLONE_SYNC_RUN_ON_STARTUP=true
RCLONE_SYNC_SCHEDULE=0 3 * * *
RCLONE_SYNC_SOURCE_REMOTE=src
RCLONE_SYNC_SOURCE_BUCKET=your_b2_bucket_name
RCLONE_SYNC_SOURCE_PATH=your/source/prefix
RCLONE_CONFIG_SRC_TYPE=b2
RCLONE_CONFIG_SRC_ACCOUNT=your_b2_key_id
RCLONE_CONFIG_SRC_KEY=your_b2_application_key
RCLONE_SYNC_TARGET_REMOTE=dst
RCLONE_SYNC_TARGET_PATH=backup/b2-archive
RCLONE_CONFIG_DST_TYPE=drive
RCLONE_CONFIG_DST_SCOPE=drive
RCLONE_CONFIG_DST_CLIENT_ID=your_google_oauth_client_id
RCLONE_CONFIG_DST_CLIENT_SECRET=your_google_oauth_client_secret
RCLONE_SYNC_TARGET_CONFIG_TOKEN_REFRESH_TOKEN=your_google_oauth_refresh_token
这会展开为:
src:your_b2_bucket_name/your/source/prefix -> dst:backup/b2-archive
Google Drive 没有 bucket。Google Drive 目标目录只填 RCLONE_SYNC_TARGET_PATH。
确认 dry-run 日志后,真实执行只改这两行:
RCLONE_SYNC_DRY_RUN=false
RCLONE_SYNC_ALLOW_DESTRUCTIVE=true
archive 是 rclone move:传输成功后删除源端文件。默认还会删除空源目录:
RCLONE_SYNC_DELETE_EMPTY_SOURCE_DIRS=true
本地目录归档时如果不想删除空目录,设为:
RCLONE_SYNC_DELETE_EMPTY_SOURCE_DIRS=false
| 模式 | 底层命令 | 删除源端 | 删除目标端多余文件 | 用途 |
|---|---|---|---|---|
copy | rclone copy | 否 | 否 | 普通复制、备份、目标保留历史 |
mirror | rclone sync | 否 | 是 | 目标严格镜像源端 |
archive | rclone move | 是,传输成功后 | 否 | 把旧数据搬到目标后释放源端空间 |
prune | rclone delete | 是 | 无目标 | 只清理源端过期数据 |
check | rclone check | 否 | 否 | 校验源和目标 |
默认安全:
RCLONE_SYNC_DRY_RUN=true
会删除数据的真实执行必须同时设置:
RCLONE_SYNC_DRY_RUN=false
RCLONE_SYNC_ALLOW_DESTRUCTIVE=true
RCLONE_SYNC_ALLOW_DESTRUCTIVE 必须来自环境变量。YAML 里不能绕过这个确认。
默认删除保护:
RCLONE_SYNC_MAX_DELETE=1000
RCLONE_SYNC_MAX_DELETE_SIZE=100G
如果不填这两个,默认仍然生效。
archive 和 prune 删除的是源端文件。runner 会先用 rclone lsjson 枚举匹配文件,检查数量和大小,超过上限就中止。
mirror 删除的是目标端多余文件。runner 会把限制传给 rclone 的 --max-delete,如果当前 rclone 支持也会传 --max-delete-size。
调整上限:
RCLONE_SYNC_MAX_DELETE=10000
RCLONE_SYNC_MAX_DELETE_SIZE=500G
明确要关闭限制时:
RCLONE_SYNC_ALLOW_UNLIMITED_DELETE=true
不建议一开始关闭删除保护。
可以直接写 root:
RCLONE_SYNC_SOURCE_ROOT=src:my-bucket/source-prefix
RCLONE_SYNC_TARGET_ROOT=dst:backup/b2-archive
也可以拆开写,适合 Docker env:
RCLONE_SYNC_SOURCE_REMOTE=src
RCLONE_SYNC_SOURCE_BUCKET=my-bucket
RCLONE_SYNC_SOURCE_PATH=source-prefix
上面生成:
src:my-bucket/source-prefix
B2、S3、R2 通常有 bucket:
RCLONE_SYNC_SOURCE_REMOTE=src
RCLONE_SYNC_SOURCE_BUCKET=my-bucket
RCLONE_SYNC_SOURCE_PATH=logs/app1
Google Drive 通常没有 bucket:
RCLONE_SYNC_TARGET_REMOTE=dst
RCLONE_SYNC_TARGET_PATH=backup/b2-archive
远端根路径默认拒绝,例如 src:、src:/、src://。如果真的要操作远端根,必须显式设置:
RCLONE_SYNC_ALLOW_ROOT_PATH=true
不建议这样做。
源端和目标端目录结构保持一致。配置两个 root,再配置一组相对目录:
RCLONE_SYNC_SOURCE_ROOT=src:my-bucket/source-prefix
RCLONE_SYNC_TARGET_ROOT=dst:backup/b2-archive
RCLONE_SYNC_DIRECTORIES=photos,documents,logs/app1
展开后:
src:my-bucket/source-prefix/photos -> dst:backup/b2-archive/photos
src:my-bucket/source-prefix/documents -> dst:backup/b2-archive/documents
src:my-bucket/source-prefix/logs/app1 -> dst:backup/b2-archive/logs/app1
同步整个 root:
RCLONE_SYNC_DIRECTORIES=.
directories 必须是相对目录,不能以 / 开头,不能包含 ..。
时间过滤基于 rclone 看到的文件修改时间,不是对象创建时间。
不填时间过滤时,处理所选目录里的全部文件:
# 不设置 RCLONE_SYNC_OLDER_THAN / DATE_BEFORE / DATE_AFTER
只处理 3 天以前:
RCLONE_SYNC_OLDER_THAN=3d
只处理约 90 天以前:
RCLONE_SYNC_OLDER_THAN=3M
M 按 30 天计算,y 按 365 天计算。需要精确日历边界时,用绝对日期:
RCLONE_SYNC_DATE_BEFORE=2026-01-01
只处理某日期之后:
RCLONE_SYNC_DATE_AFTER=2025-01-01
只处理日期窗口:
RCLONE_SYNC_DATE_AFTER=2025-01-01
RCLONE_SYNC_DATE_BEFORE=2026-01-01
如果 DATE_BEFORE 是未来日期,runner 会拒绝执行,避免误把全部文件当成匹配。
按后缀排除:
RCLONE_SYNC_EXCLUDE_EXTENSIONS=.tmp,.part,.bak
按 rclone glob 排除:
RCLONE_SYNC_EXCLUDE=**/cache/**,**/.DS_Store,**/*.iso
使用过滤文件:
RCLONE_SYNC_EXCLUDE_FROM=/filters/exclude.txt
Compose 挂载:
volumes:
- ./filters:/filters:ro
示例见 filters/exclude.txt.example。
env 里必须使用容器内路径,不是宿主机路径。
B2 到本地目录:
services:
rclone-sync:
image: your-dockerhub-user/rclone-sync:latest
env_file:
- ./b2-to-local.env
volumes:
- /srv/b2-backup:/data/target
- ./logs:/logs
- ./state:/state
env 示例见 examples/b2-to-local.env.example。
本地目录到 Google Drive:
services:
rclone-sync:
image: your-dockerhub-user/rclone-sync:latest
env_file:
- ./local-to-google-drive.env
volumes:
- /srv/source:/data/source:ro
- ./logs:/logs
- ./state:/state
env 示例见 examples/local-to-google-drive.env.example。
rclone 里 Google Drive backend 类型叫 drive:
RCLONE_CONFIG_DST_TYPE=drive
纯 env OAuth 至少需要:
RCLONE_CONFIG_DST_TYPE=drive
RCLONE_CONFIG_DST_SCOPE=drive
RCLONE_CONFIG_DST_CLIENT_ID=your_google_oauth_client_id
RCLONE_CONFIG_DST_CLIENT_SECRET=your_google_oauth_client_secret
RCLONE_SYNC_TARGET_CONFIG_TOKEN_REFRESH_TOKEN=your_google_oauth_refresh_token
client_id 和 client_secret 只是 OAuth 应用凭证,不能单独访问某个 Drive。refresh_token 代表用户授权过这个应用访问 Drive。
access_token 和 expiry 不需要填。runner 会自动组装 rclone token,rclone 会自己刷新。
不用 rclone 获取 refresh token:
python3 tools/google-drive-refresh-token.py ./client_secret.json
脚本只使用 Python 标准库。浏览器授权后输出:
RCLONE_SYNC_TARGET_CONFIG_TOKEN_REFRESH_TOKEN=...
也可以使用 Google OAuth Playground。Scope 用:
https://www.googleapis.com/auth/drive
如果你已经有主机上的 rclone remote,例如 gt::
rclone lsd gt:
可以挂载 rclone.conf:
volumes:
- ~/.config/rclone:/config/rclone
然后目标写:
RCLONE_SYNC_TARGET_ROOT=gt:backup/b2-archive
这种模式下不要再配置 RCLONE_CONFIG_DST_*。
rclone 原生 env remote 格式:
RCLONE_CONFIG_<REMOTE_NAME>_<OPTION_NAME>
remote 名全部大写。例如路径使用 src::
RCLONE_SYNC_SOURCE_ROOT=src:my-bucket/source-prefix
RCLONE_CONFIG_SRC_TYPE=b2
RCLONE_CONFIG_SRC_ACCOUNT=your_b2_key_id
RCLONE_CONFIG_SRC_KEY=your_b2_application_key
Cloudflare R2 / S3 示例:
RCLONE_SYNC_SOURCE_ROOT=src:my-bucket/source-prefix
RCLONE_CONFIG_SRC_TYPE=s3
RCLONE_CONFIG_SRC_PROVIDER=Cloudflare
RCLONE_CONFIG_SRC_ACCESS_KEY_ID=your_access_key_id
RCLONE_CONFIG_SRC_SECRET_ACCESS_KEY=your_secret_access_key
RCLONE_CONFIG_SRC_ENDPOINT=https://account-id.r2.cloudflarestorage.com
RCLONE_CONFIG_SRC_REGION=auto
快速示例建议固定使用 src 和 dst。如果自定义 remote 名,例如 gdrive:,也要同步改成对应的 RCLONE_CONFIG_GDRIVE_*,或用 RCLONE_SYNC_TARGET_ROOT=gdrive:path 配合 RCLONE_SYNC_TARGET_CONFIG_*。
填 webhook 后会发送通知:
RCLONE_SYNC_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz
RCLONE_SYNC_SLACK_EVENTS=startup,job_start,job_success,job_error,task_start,task_success,task_error
可选项:
RCLONE_SYNC_SLACK_USERNAME=rclone-sync
RCLONE_SYNC_SLACK_CHANNEL=#backups
RCLONE_SYNC_SLACK_TIMEOUT=10
事件:
| 事件 | 说明 |
|---|---|
startup | 容器 entrypoint 启动 |
job_start | 一个 job 开始 |
job_success | 一个 job 成功 |
job_error | 一个 job 失败 |
task_start | 一个目录 task 开始 |
task_success | 一个目录 task 成功,包含耗时和预检候选数量 |
task_error | 一个目录 task 失败 |
Slack 发送失败不会中断同步,只写容器日志。
不设置 schedule 时,容器启动后执行一次,然后退出。
RCLONE_SYNC_SCHEDULE=
设置 5 字段 cron 后,容器常驻:
RCLONE_SYNC_RUN_ON_STARTUP=true
RCLONE_SYNC_SCHEDULE=0 3 * * *
时区来自:
TZ=Asia/Shanghai
如果设置了 schedule 且启动任务失败,容器会退出;配合 restart: unless-stopped 时会重启。这样可以让错误显性暴露,而不是静默等待下一次 cron。
建议始终挂载:
volumes:
- ./logs:/logs
- ./state:/state
每次运行写入:
/logs/runs/<timestamp>/<job>/<task>/command.json/logs/runs/<timestamp>/<job>/<task>/result.json/logs/runs/<timestamp>/<job>/<task>/combined.txt/logs/runs/<timestamp>/<job>/<task>/errors.txt这些日志包含 bucket、prefix、文件名和命令参数,属于敏感运行数据,不要提交到 git。
当前镜像默认以 root 运行,logs/ 和 state/ 里可能产生 root-owned 文件。需要清理时可用 sudo rm -rf logs state,或在自己的 compose 中增加合适的 user: 设置并确认挂载目录权限。
看日志:
docker logs rclone-sync
用 compose 看日志:
docker compose logs -f rclone-sync
进入容器调试 rclone:
docker compose run --rm rclone-sync rclone lsd dst:
只手动跑一次:
docker compose run --rm rclone-sync run
一个常见任务用 env 即可。多个 job 或复杂规则可以挂载 /config/jobs.yaml:
services:
rclone-sync:
image: your-dockerhub-user/rclone-sync:latest
volumes:
- ./config.example.yaml:/config/jobs.yaml:ro
- ~/.config/rclone:/config/rclone
- ./logs:/logs
- ./state:/state
YAML 中即使配置了 destructive job,真实删除仍然需要环境变量:
RCLONE_SYNC_ALLOW_DESTRUCTIVE=true
.gitignore 和 .dockerignore 已忽略 tmp/、logs/、state/、rclone-sync.env、.env 和常见密钥文件。rclone/rclone:1.70.3,发布自己的镜像时建议同时打版本 tag 和 latest。发布到 Docker Hub 可以用整个仓库根目录的公共脚本 ../publish-dockerhub.sh。这个脚本可以发布不同目录里的 Dockerfile,靠 --context 和 --file 指定要构建哪个 Docker。
cd /home/sean/git/dockers
./publish-dockerhub.sh \
--context rclone-sync \
--file Dockerfile \
--image your-dockerhub-user/rclone-sync \
--tag 0.1.0
脚本默认会:
linux/amd64,linux/arm64。your-dockerhub-user/rclone-sync:0.1.0。your-dockerhub-user/rclone-sync:latest。如果要自动登录 Docker Hub:
DOCKERHUB_USERNAME=your-dockerhub-user \
DOCKERHUB_TOKEN=your_dockerhub_access_token \
./publish-dockerhub.sh \
--context rclone-sync \
--file Dockerfile \
--image your-dockerhub-user/rclone-sync \
--tag 0.1.0
只发布指定 tag,不更新 latest:
./publish-dockerhub.sh \
--context rclone-sync \
--file Dockerfile \
--image your-dockerhub-user/rclone-sync \
--tag 0.1.0 \
--no-latest
本地测试构建,不推送:
./publish-dockerhub.sh \
--context rclone-sync \
--file Dockerfile \
--image your-dockerhub-user/rclone-sync \
--tag 0.1.0 \
--platforms linux/amd64 \
--load
已经真实测试过:
archive 模式。RCLONE_SYNC_OLDER_THAN=24h 时间过滤。.tmp/.part/.bak 后缀排除。startup/job_start/task_start/task_success/job_success 通知。Content type
Image
Digest
sha256:0cdb18c9a…
Size
45.8 MB
Last updated
4 months ago
docker pull xzsean/rclone-sync