关联主题:: 图床
同级:: 2025-09-18_星期四
下一级::
方案一:手动克隆+拉取
1、进入nas想要备份的目录;
2、执行一次克隆
git clone xxx #github仓库地址
3、以后只需进入这个目录,执行
git pull
就能把最新的图床更新拉到 NAS。
✅ 简单,缺点是需要你手动执行。
方案一属于增量更新。
增量更新
git pull
本质上是 增量更新 ✅,不会每次都全量下载。
具体来说:
- 第一次
git clone
会把仓库完整拉下来(全量)。- 之后执行
git pull
时,Git 会:
- 检查本地分支和远程分支的差异
- 只下载新增的 commit 对象(即增量部分)
- 把这些新对象合并到你的本地分支
所以哪怕你的仓库里有几千张图片,每次git pull
只会把新上传的图片(以及元数据变更)同步下来。
⚠️ 例外情况:- 如果本地仓库损坏或
.git
丢失,重新git clone
才是全量。- 如果远程仓库被强制推送(
git push --force
),本地可能需要git fetch --all && git reset
,这时候等于重新对齐。
👉 总结:正常情况下,git pull
是增量更新,非常高效。
方案二:Docker自动定时同步
1、创建文件夹
mkdir -p /volume2/docker/git-sync
cd /volume2/docker/git-sync
2、新建docker-compose.yml
我直接使用nas的图形化操作界面配置的项目
version: "3.8"
services:
git-sync:
image: alpine:3.20
container_name: git-sync
restart: unless-stopped
environment:
TZ: Asia/Singapore
# 仓库配置(这里要改成带 Token 的 HTTPS 地址)
REPO_URL: "https://<用户名>:<token>@github.com/brmysss/pic.git"
BRANCH: "main"
WORKTREE: "/data"
SPARSE_PATH: ""
CRON_SCHEDULE: "0 * * * *"
# 代理设置
HTTP_PROXY: "http://192.168.10.2:7890"
HTTPS_PROXY: "http://192.168.10.2:7890"
NO_PROXY: "localhost,127.0.0.1"
volumes:
- /volume2/docker/git-sync/data:/data
- /volume2/docker/git-sync/scripts/sync.sh:/usr/local/bin/sync.sh:ro
- /volume2/docker/git-sync/scripts/entrypoint.sh:/entrypoint.sh:ro
entrypoint: ["/entrypoint.sh"]
有几个点要注意:
- REPO_URL:https://brmysss:ghp_xxxxxxxxxxxxxxxxxxxxx@github.com/brmysss/pic.git
brmysss是用户名,ghp_xxx...
是你生成的 GitHub Personal Access Token - CRON_SCHEDULE:
"0 * * * *"
这里设置的是定时同步的时间; - 配置代理:
HTTP_PROXY: “http://192.168.10.2:7890”
HTTPS_PROXY: “http://192.168.10.2:7890”
NO_PROXY: “localhost,127.0.0.1”
3、创建三个文件夹
mkdir -p /volume2/docker/git-sync/data
mkdir -p /volume2/docker/git-sync/scripts
mkdir -p /volume2/docker/git-sync/ssh
执行完你会看到结构:
/volume2/docker/git-sync/
├── data/
├── scripts/
└── ssh/
4、创建脚本
- 第 1 步:创建脚本
在/volume2/docker/git-sync/scripts/
下创建两个文件:
① entrypoint.sh
路径:/volume2/docker/git-sync/scripts/entrypoint.sh
内容:
#!/bin/sh
set -e
# 安装必要依赖
apk add --no-cache git bash tzdata ca-certificates openssh-client
# 如果设置了代理,让 git 也走代理
[ -n "$HTTPS_PROXY" ] && git config --global http.proxy "$HTTPS_PROXY"
[ -n "$HTTPS_PROXY" ] && git config --global https.proxy "$HTTPS_PROXY"
# 写入 cron 配置(每小时跑一次)
echo "${CRON_SCHEDULE} /usr/local/bin/sync.sh >> /var/log/git-sync.log 2>&1" > /etc/crontabs/root
# 启动时先同步一次,再常驻
bash /usr/local/bin/sync.sh
crond -f -L /var/log/cron.log
② sync.sh
路径:/volume2/docker/git-sync/scripts/sync.sh
内容:
#!/usr/bin/env bash
set -euo pipefail
REPO_URL="${REPO_URL:?REPO_URL is required}"
BRANCH="${BRANCH:-main}"
WORKTREE="${WORKTREE:-/data}"
SPARSE_PATH="${SPARSE_PATH:-}"
echo "[$(date '+%F %T')] Start sync -> $REPO_URL ($BRANCH) -> $WORKTREE sparse:'$SPARSE_PATH'"
mkdir -p "$WORKTREE"
cd "$WORKTREE"
# 如果第一次运行,还没有 .git,就初始化
if [ ! -d ".git" ]; then
git init
git remote add origin "$REPO_URL"
if [ -n "$SPARSE_PATH" ]; then
git config core.sparseCheckout true
mkdir -p .git/info
echo "$SPARSE_PATH" > .git/info/sparse-checkout
fi
git fetch --depth=1 origin "$BRANCH"
git checkout -f "origin/$BRANCH"
else
# 已经有仓库,直接更新
if [ -n "$SPARSE_PATH" ]; then
git config core.sparseCheckout true
echo "$SPARSE_PATH" > .git/info/sparse-checkout
fi
git fetch --prune origin "$BRANCH"
git reset --hard "origin/$BRANCH"
fi
# 清理历史对象
git gc --prune=now --aggressive || true
echo "[$(date '+%F %T')] Sync done."
给脚本执行权限
chmod +x /volume2/docker/git-sync/scripts/entrypoint.sh
chmod +x /volume2/docker/git-sync/scripts/sync.sh
5、生成SSH部属密钥
在 NAS 上执行:
cd /volume2/docker/git-sync/ssh
# 生成密钥对(一路回车即可,不要设置密码)
ssh-keygen -t ed25519 -N "" -f id_ed25519
# 加入 GitHub 主机指纹,避免首次连接提示 yes/no
ssh-keyscan github.com >> known_hosts
生成后,你会得到:
id_ed25519
(私钥,留在 NAS,不要泄露)id_ed25519.pub
(公钥,下一步要加到 GitHub 仓库)known_hosts
6、第 3 步:把公钥加到 GitHub 仓库
- 登录 GitHub,进入你的仓库 brmysss/pic
- 点右上角 Settings → Deploy keys → Add deploy key
- Title 随便写(如
NAS sync
) - Key:粘贴
id_ed25519.pub
的内容 - 勾选 Allow read access(不要勾写权限)
- 保存
不出意外的话,就可以同步内容了
现在的容器已经能正常跑起来的话,流程就是这样的:
- 容器启动时
entrypoint.sh
会先执行一次sync.sh
。sync.sh
里会去 git clone / git fetch 你的 GitHub 仓库。- 同步结果写到容器里的
/data
路径。- 因为你在 volumes 里挂载了
- /volume2/docker/git-sync/data:/data
所以容器里的/data
↔ NAS 的/volume2/docker/git-sync/data
是绑定的。
👉 仓库文件就会直接落到你 NAS 上这个文件夹里。- 之后每小时
cron
会再自动跑一次sync.sh
,把远端仓库的更新增量拉取到 NAS。
如果中途遇到什么问题,可以直接和AI进行对话解决。
总结
目标:
👉 让 GitHub 私有仓库(图床) 自动同步到 NAS 的文件夹,每小时更新一次。
方式:
👉 用一个容器(git-sync
),里面跑 git
和 cron
定时任务。
👉 NAS 上有几个文件夹,分别放 数据、脚本、配置。
📂 文件夹结构说明
我们一共在 NAS 上建了一个大文件夹 /volume2/docker/git-sync
,里面分了几个子文件夹:
/volume2/docker/git-sync
├── data/ # 仓库同步后的内容,GitHub 的文件就存到这里
├── scripts/ # 两个脚本:entrypoint.sh(启动入口)、sync.sh(同步逻辑)
└── docker-compose.yml # 容器配置文件
1. data/
- 这是 仓库内容最终落地的地方。
- 里面有:
.git/
(Git 用来存历史),以及你的img/
文件夹、README.md
等。 - 以后你只要去
/volume2/docker/git-sync/data
看,就能看到和 GitHub 一模一样的文件。
2. scripts/
这个文件夹里有两个脚本:
sync.sh
- 作用:定义 “同步一次”要做什么。
- 逻辑就是:
- 如果
data/
还是空的,就git clone
- 如果已经有仓库了,就
git fetch
+git reset
(强制对齐远端)
- 如果
- 每次同步都会把 GitHub 最新内容拉下来,保证和远端一致。
entrypoint.sh
- 作用:容器启动时的“入口”。
- 逻辑就是:
- 安装
git
和cron
- 写一条定时规则到 crontab(
0 * * * *
→ 每小时执行一次sync.sh
) - 先手动跑一次
sync.sh
(启动时就同步一次) - 启动
cron
并保持容器不退出
- 安装
👉 简单理解:entrypoint.sh
= 开机启动 + 定时器设置。
3. docker-compose.yml
- 这是容器的“配置文件”,告诉 Docker:
- 用
alpine:3.20
镜像(轻量 Linux) - 环境变量(仓库地址、分支、代理、定时规则等)
- 挂载目录:把 NAS 上的
/volume2/docker/git-sync/data
挂进容器的/data
- 用
👉 简单理解:这是“启动容器”的说明书。
📜 日志在哪里?
有两个日志文件,都是在 容器里,不是 NAS 外面直接看的:
/var/log/git-sync.log
- 每次
sync.sh
跑的时候,会把输出追加到这里。 - 你可以通过 容器终端 或 容器日志界面看到
- 每次
/var/log/cron.log
- 这是
crond
定时器的日志,能看到定时任务有没有触发。
- 这是
怎么查看?
方法有两种:
方法1:在 容器管理界面 → 选中 git-sync
→ 点 日志
👉 这是最简单的方式,你平时只要看这里就行。
方法2:在 容器终端里手动看
tail -n 50 /var/log/git-sync.log
tail -n 50 /var/log/cron.log
✅ 整体运行流程
- 你启动容器 →
entrypoint.sh
会:- 装软件
- 写入定时任务
- 先跑一次
sync.sh
sync.sh
会:- 确认远端地址
- 拉取 GitHub 仓库最新内容到
/data
- 之后每到整点(0:00、1:00、2:00…) →
cron
自动执行sync.sh
👉/data
永远保持和 GitHub 仓库一致。
如何手动同步?
方法 1:在容器终端里运行
- 打开 git-sync 容器 → 终端
- 输入:
/usr/local/bin/sync.sh && echo "manual sync OK"
- 如果一切正常,会打印:
Start sync -> https://github.com/... ... Sync done. manual sync OK
👉 这样就等于立刻把 GitHub 最新内容拉到 NAS。
方法 2:在 NAS 主机直接运行(推荐只在容器里跑)
因为 sync.sh
是放在容器里的,如果你在 NAS 主机直接跑,需要进入容器执行:
docker exec -it git-sync /usr/local/bin/sync.sh
👉 这样不用打开图形界面终端,SSH 连 NAS 就能同步。