docker系列使用docker基於syncthing實作多點資料夾同步之詳細教學
本文最後更新於271 天前,其中的資訊可能已經有所發展或是發生改變,如有失效可到評論區留言。

前言

其實,咋一想的話,資料夾同步這個需求,網路解決方案貌似很多,搜尋了半天,結合自己的使用經驗,我簡單的把這些沾邊的解決方案分為3類:
1、單APP類方案
以sync folders為代表,區域網路範圍的win、macos系統可用,使用簡單,缺點是只能區域網路範圍使用,且只支援win和macos,講道理,還是非常好用的:

image.png

2、網盤類解決方案
以nextcloud為代表:
image.png

這類個人網盤類應用,往往需要先部署server端,然後其他各個需要同步資料的節點透過安裝client端連接server端來使用,優點是可以跨廣域網路使用,缺點是client端只能桌上型系統,且server端部署需要公網IP位址,同時client同步的速度受限於client和server端之間的連線速度(可以透過為server端部署CDN的方式來解決速度問題)。
3.基於第3方儲存類別備份同步方案

以rclone、duplicati為代表,這類方案將需要備份或同步的檔案都存放在第3方儲存上,然後各個節點都部署應用,透過存取第3方儲存來實現備份或同步檔案的目的:例如rclone支援40 多種雲端存儲,從普通的網盤(OneDrive、Google Drive、Dropbox 等)到雲端物件儲存(Amazon S3、阿里雲OSS等)再到各種傳輸協定(FTP、SFTP、WebDav)。

在這3類方案中,第3種方案的適應性最廣,以rclone為例:既可以支援跨廣域網,又能夠同時支援桌面系統和cli介面,不過麻煩的是需要使用第3方儲存作為中轉(或者有公網IP可以自建FTP、SFTP、WebDav),並且本質上這類方案主要的目的是備份本地資料到雲端儲存或把雲端儲存上的資料拉回本地,其主要目的其實還是是備份和恢復,雖然可以透過alist之類的方法將雲盤資料掛載到本地(rclone本身就支援掛載),但是這個和傳統意義上的資料夾資料同步的需求還是不一樣的。

那如果我只是想簡單的跨廣域網路在不同系統之間(macos、linux、win)定時同步幾個目錄,不想折騰其他有的沒的,有沒有辦法呢?

還是有,那就是這篇文章要介紹的網路本身為基礎的專業同步工具:syncthing。

syncthing實作原理

syncthing其實只是一個不需要安裝的可執行程序,它不需要像nextcloud那樣提前部署server端,也不需要像rclone一樣借助第3方存儲,只需要在各個需要同步數據的設備上直接運行syncthing,然後簡單設定一下就行了。

同樣都是可執行程式的方式,syncthing和前面提到的sync folders相比適用性如何呢?這要看需要同步的網路環境是區域網路範圍還是廣域網路範圍,並且使用端是桌面端還是cli端了。
1、區域網路環境
1.1、純桌面端
這種情況下,講道理,如果需要資料夾同步的節點都是桌面端,我覺得sync folders貌似更好使,這種情況下syncthing沒太大優勢。
1.2、桌面端、CLI端混雜
這種情況下,就可以使用syncthing了:可以在所有端都部署syncthing;也可以桌面端部署sync folders,CLI端部署syncthing,最後拿一個端同時部署sync folders和syncthing,就可以全部打通,不過這種方式需要注意同步的方向問題:例如可以設定一台CLI端syncthing為僅發送,其他CLI端的syncthing為僅接收,然後透過同時部署sync folders和syncthing的端將內容同步到所有桌面端去(sync folders也可以透過設定同步類型來實現只發送或只接收的效果)。
2、廣域網路環境
這種情況下,不管是桌面端還是CLI端,直接全部部署syncthing就行了。

為什麼syncthing能夠不借助第3方直接實現跨廣域網路同步呢?這其實是依賴syncthing的發現伺服器和中繼伺服器。

syncthing的"設定"-"連接"的介面如下:

image.png

啟用全域發現功能以後,在跨廣域網路時就能提供stun服務幫助使用者進行NAT穿透。


上圖中提到的到"全域發現"和"啟用中繼"這2個選項,包含兩個重要的功能:syncthing的連線通告服務和中繼服務。
1、連線通告服務:
連線通告服務的功能是在一個syncthing端點主動新增另一個syncthing端點時,另一個端點會收到連線通告服務發出的通知,詢問是否接受,如果這個端點選擇接受,兩個端點就會成功的相互添加對方為遠端設備。
2、中繼服務:
中繼服務其實包含了2個獨立的部分:stun服務和turn服務。 stun服務會收到雙方發送的資訊(網卡IP、監聽埠等),當然,這個資訊一般都不能直接使用(可能是內網資訊),需要stun服務結合自己收到syncthing的資料包的真實來源位址和連接埠一起來判斷兩個端點所處位置前的NAT類型(NAT1、2、3、4),判斷能否打洞,如果能成功打洞,雙方就能直接根據stun提供的資訊進行點對點連接,這種同步檔案的速度就會比較快;而如果不能打洞,就只能交給turn伺服器全權處理了,這種同步檔案的速度就會比較慢,取決於中繼伺服器給每個使用者分配的頻寬(具體速度還要除以2)以及使用的人數多少。

因為syncthing本來在網路上就部署了公用的發現伺服器和中繼伺服器,所以我們部署的syncthing才能在廣域網路上直接使用,只不過,使用的體驗取決我們本身的NAT類型、我們部署的syncthing端和發現伺服器以及中繼伺服器的通訊效果等(預設提供的發現伺服器和中繼伺服器都是國外的,國內使用的體驗肯定好不到哪裡去~)。


順便提一下,在syncthing的高階設定裡其實是可以看到stun相關的設定的,Stun Server還可以直接設定為你自己搭建的stun伺服器:

image.png

這是因為NAT穿透其實就是基於stun服務(stun的原理以及如何搭建自己的stun伺服器可以參見我另一篇文章:docker系列使用docker基於coturn搭建自己的stun/turn伺服器),所以要取得最好的效果,而你不怕折騰,可以使用自己搭建的stun伺服器、自己搭建的發現伺服器、自己搭建的中繼伺服器。 。這個我後面的章節會單獨講。

部署syncthing

直接使用syncthing的可執行程序

github上的下載連結為:https://github.com/syncthing/syncthing/releases

其實,講道理,syncthing在linux上就是一個可執行文件,下載後賦予執行權限,然後直接運行就好了,不一定非要折騰docker,還不會遇到啥權限問題,只是需要注意,最好使用一個非root的一般權限帳號來運作。

我部署的方式還是選擇docker,原因只是因為統一到docker上方便管理和記憶:畢竟年紀大了,我怕我以後記不住到底部署了多少腳本。 。 。

使用docker方式建構syncthing

在宿主機上建立需要對應到容器內部的目錄

mkdir -p /docker/syncthing/config #用於存放syncthing設定檔mkdir -p /docker/syncthing/data #用於存放需要同步的數據

搭建syncthing

docker run格式的指令如下:

docker run --name syncthing -d --restart=always \ --hostname=syncthing #可選項\ -e PUID=1000 -e PGID=1000 \ #可選項,如果docker存取掛載的目錄出現權限問題的時候可以採用,在宿主機裡的使用id username命令來獲取PUID和PGID -e TZ=Asia/Shanghai \ #指定時區-p 8384:8384 \ # 管理gui的端口,請根據自己實際環境情況指定-p 22000 :22000/tcp \ #指定宿主機上tcp的監聽端口,請根據自己實際情況修改,最好不變-p 22000:22000/udp \ #指定宿主機上udp的監聽端口,請根據自己實際環境修改,最好不變-p 21027:21027/udp \ #發現協議使用的端口,請根據自己實際環境修改,最好不變-v /docker/syncthing/config:/config \ #掛載宿主機上的指定目錄到容器內部特定路徑,這裡是設定檔所在目錄-v /docker/syncthing/data:/data1 \ #掛載宿主機上的指定目錄到容器內部特定路徑,這裡主要是需要同步的資料所在的目錄,可以指定多個,例如data2,data3等,也可以直接將宿主機上原有的需要同步的目錄直接映射過來,不過需要注意權限問題,比如755改成777,否則可能會同步不了,不要問我怎麼知道的。 lscr.io/linuxserver/syncthing:latest

註:請自行刪掉#及其後面的註解內容。

其實,如果主要是區域網路內使用且需要使用區域網路主動發現,且8384 tcp 、22000 tcp/udp 、21027 udp這幾個連接埠又沒有使用的話,可以直接用host類型部署(注意:這種部署方式linux下有效,macos下是無效的),docker run格式指令如下:

docker run --name syncthing -d --restart=always --net=host \ --hostname=syncthing \ -e TZ=Asia/Shanghai \ -v /docker/syncthing/config:/config \ -v /docker/ syncthing/data:/data1 \ lscr.io/linuxserver/syncthing:latest

依序以docker方式建立3個syncthing節點:syncthing-macmini、syncthing-intermini,syncthing-tc。 syncthing-macmini部署在我的m1 macmini 8g乞丐版上,採用-p映射埠方式部署(docker在macos上不支援host方式部署);syncthing-intermini部署在我的13代i5 cpu的高檔mini主機上,位於和syncthing-macmin同一個區域網路區段,採用host方式部署(為了後面的試驗);syncthing-tc部署在騰訊雲端輕量伺服器上,和syncthing-macmini一樣,採用-p映射埠的方式部署(因為就算以host方式部署也沒用)。

配置syncthing

初始化

使用http://宿主機ip:8384訪問syncthing-macmini,初次訪問會彈出如下詢問,這個大家隨意選擇,是或否都行:

image.png

進入介面之後首先需要建立管理員使用者名稱密碼:
image.png

image.png

設定完成後會彈出登入認證頁面,使用剛才建立的使用者名稱密碼登入:
image.png

然後進入正式的配置頁面:
image.png

同理初始化syncthing-intermini和syncthing-tc。

註:初始化所有節點的時候先不用再加入同步資料夾,後面一起設定。

新增遠端設備

在syncthing-macmini端開始新增其他兩個節點。

新增syncthing-intermini節點

直接點擊遠端設備部分紅框中的"新增遠端設備":

image.png

因為syncthing-intermini是採用host方式部署的,所以在下圖中可以直接從附近的裝置看到:
image.png


如果不是採用host方式部署,則無法在附近的裝置中看到,所以需要單獨去syncthing-intermini複製設備id:

image.png

image.png


image.png

image.png

然後登入syncthing-intermini節點上,可以看到有來自syncthing-macmini的新增請求:
image.png

點擊添加設備以後會出現syncthing-macmini的具體信息,這個時候,直接點擊右下角保存即可:
image.png

然後可以看到syncthing-intermini的遠端設備已經有了syncthing-macmini:
image.png

然後我們可以看到syncthing-macmini上也已經成功添加了syncthing-intermini的遠端設備:

image.png

上圖中一大堆位址,是因為我們在macmini上新增intermini時候,位址清單我們選擇了預設的dynamic,所以是透過預設的公網上的stun伺服器和中繼伺服器,一起來判斷有哪些連線的方式,導致下面這麼一大堆的選擇,有些可用,有些不可用。其實對於同一個區域網路內的設備而言,沒必要整這麼複雜,所以我們可以直接在syncthing-macmini上的遠端設備中,修改syncthing-intermini的位址列表,將預設的dynamic修改為tcp://intermini區域網路IP:22000,如下圖:
image.png

然後可以看到,遠端設備中,syncthing-intermini的位址已經變了:
image.png

而同時,在syncthing-intermini中,遠端設備syncthing-macmini的位址也變了:
image.png

新增syncthing-tc節點

同理添加syncthing-tc節點,只不過因為這是騰訊雲端輕量伺服器上的節點,如果需要使用公網IP連線的話,需要提前在控制台的防火牆裡開啟22000 tcp/udp、8384 tcp、21027 udp這些連接埠:

image.png

image.png

至此,在syncthing-macmini上已經成功新增其他兩個節點:
image.png

新增同步資料夾

在主節點上先新增同步資料夾

假設我們需要同步的內容位於syncthing-macmini容器內/data1目錄,那麼我們需要先在主節點syncthing-macmini上新增:

image.png

image.png

image.png

image.png

image.png

image.png

如果前面勾選了增加忽略模式,就會出現如下介面:
image.png

隨後同步資料夾就成功加入了:
image.png

註:syncthing會在新增的同步資料夾裡新建一個名為".stfolder"的目錄,如果因為權限問題無法新增這個目錄,會在web頁面上提示無法建立這個資料夾。大家看到這種報錯就要知道出現了權限問題:如果是docker環境,就要考慮使用-e PUID= -e PGID=的參數指定合理的宿主機真實使用者權限,或把宿主機上對應到容器內部的目錄權限從755改為777;如果是直接執行syncthing執行檔的方式,可以直接使用修改目錄權限的方式。

將主站上的同步資料夾共用給其他節點

image.png

因為我前面在建立資料夾的時候已經設定好了版本控制、忽略模式、進階等選擇,所以這裡直接在共用中選擇2個遠端裝置然後直接儲存即可,如下圖:
image.png

然後在其他兩個節點上會分辨收到來自syncthing-macmini的共用資料夾請求:
image.png

image.png

點擊紅框中的"新增"後,會進入新增同步資料夾的選項:
image.png

image.png

image.png

同理在syncthing-tc節點上也完成一樣的步驟,最後完成後可以在syncthing-macmini節點看到同步狀況:
image.png

註:同步速度取決於syncthing節點之間能否選擇最優的路徑,如果沒有選擇最優路徑,就可能出現明明是同一個區域網路內,走內網傳輸最快,卻偏偏去走最慢的中繼伺服器,這是因為syncthing之間對彼此的位置判斷錯誤,這種情況在docker部署方式中很常見,而如果是linux系統且以host方式部署,那麼在同一個內網網段裡正確識別的幾率就非常高了。不過其實沒關係,只要按照我們前面講過的方法,在每個節點的遠端設備裡的位址清單裡手動指定正確的位址即可。

進階使用1:自建發現伺服器與中繼伺服器

理論上,只要我們部署syncthing是連網的環境,一般都能連接網路上的公用的syncthing發現伺服器和中繼伺服器,不過不排除有一些特殊的環境,例如純內網環境,或是營運商網路限制導致連不上公用發現伺服器和中繼伺服器,這個時候如果我們有條件(有公網IPv4的家庭寬頻、有固定公用IP的雲端主機、或純內網環境我們有可控的部署環境),是可以自建發現伺服器和中繼伺服器的,這裡我還沒準備多講,就直接把docker指令貼出來,大家有興趣可以自己研究。
發現伺服器docker run格式指令:

docker run --name syncthing_discovery_server -d --restart=always \ -e PUID=1000 -e PGID=1000 \ #和前面一樣,也是可選項-p 8443:8443 \ -v /docker/syncthing/discosrv:/var /stdiscosrv \ syncthing/discosrv:latest

中繼伺服器docker run格式指令:

docker run --name syncthing_relay_server -d --restart=always \ -e PUID=1000 -e PGID=1000 \ -e pools="" \ #這裡很重要,如果不加這個,你搭建的中繼伺服器預設會直接發佈到網路公用中繼伺服器的清單中-p 22067:22067 \ -v /docker/strelaysrv:/var/strelaysrv \ syncthing/relaysrv:latest

上面的發現伺服器和中繼伺服器的指令和映像都是官方提供的,分成2個獨立的docker,網路上也有人把這2個合為一個docker,指令如下:

docker create \ --name=syncthing-relay-discosrv \ -p 22067:22067 \ -p 22070:22070 \ -p 8443:8443 \ --restart unless-stopped \ johngong/syncthing-relay-disrv:late

我沒試過,大家有興趣可以試試。


自建的發現伺服器和中繼伺服器的設備ID在對應docker的日誌中可以查到,使用docker log 容器名字,例如,我搭建的發現伺服器設備ID:

image.png

中繼伺服器的設備ID:
image.png

syncthing在"設定"-"連接"的介面,將原來的default改為對應的發現伺服器和中繼伺服器位址,也可以保留default,將中繼伺服器和發現伺服器位址分別寫成:"default,relay:/ /"和"default,https://":
image.png

註:如果是純內網環境,就算不是一個網段,也只需要建立發現伺服器即可,用不上中繼伺服器,只不過可能需要在"遠端設備"-"高級"-"位址清單"裡手動使用"tcp://對方ip:22000"進行新增。

進階使用2:直接配合虛擬組網使用

以tailscale實作的虛擬網路網路為例,在syncthing-macmini的遠端設備syncthing-tc的位址清單裡直接使用tailscale的位址:

image.png

這種方式的好處是騰訊雲端伺服器上的防火牆連接埠都不用開,因為tailscale是直接透過wireguard vpn進入裝置內核,不走傳統的tcp協定。如果所有的節點都部署了tailscale,則彼此直接可以直接使用對方的tailscale位址進行新增即可,根本就不需要中繼伺服器。

後話

如果只是從同步的角度來講,syncthing的確是最方便的:不需要部署server端,不需要依賴第3方存儲,也同時支援gui和cli,實際使用起來也非常簡單的。

我看了一下網友遇到的各種問題,要么是權限問題、要么是不理解發現伺服器和中繼伺服器的工作機制,沒有優化配置(地址列表手動修改對端IP)而導致的速度緩慢問題。其實如果進行了正確的配置,syncthing用起來還是非常爽的(像我,內網通訊就走內網IP,廣域網路通訊就走tailscale的IP)。

我現在的3個節點:syncthing-macmini實際上是wordpress的主站、syncthing-intermini是內網中wordpress主站的熱備站,而syncthing-tc是騰訊雲主機上部署的主站的鏡像站點,現在達到的效果是主站設定了每週一次的自動備份到本機目錄(/docker/wordpress/html/wp-content/wpvividbackups):

image.png

syncthing偵測到主站的WPvivid完成了定期備份後,會自動同步到熱備站和鏡像站的WPvivid插件的相同路徑下,然後只需要在熱備站和鏡像站的WPvivid插件裡點擊下方紅框中掃描的按鍵:
image.png

主站同步過來的備份就會出現:
image.png

然後直接點擊還原即可更新為最近一次主站備份時候的內容,這總比手動上傳備份然後還原的技術逼格更高一點吧,雖然時間差不了多少。

有這個需求也是沒辦法,因為WPvivid計劃任務備份到遠端特點站點的時候,只能選擇一個站點(我現在有熱備站和鏡像站點2個,以後可能更多),並且只能是FTP或者SFTP的方式,最蛋痛的是在遠端站台掃描並還原的時候,要求輸入FTP或SFTP的資訊(IP、連接埠、使用者名稱及密碼),好煩,關鍵我常常忘記。 。 。現在有了syncthing之後,這個痛點總算解決了,心裡舒坦了。

部落格內容均係原創,轉載請註明出處!更多部落格文章,可以移步至網站地圖了解。部落格的RSS位址為:https://blog.tangwudi.com/feed,歡迎訂閱;如有需要,可加入Telegram群一起討論問題。
暫無評論

發送評論 編輯評論


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ°Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
顏文字
Emoji
小恐龍
花!
上一篇
下一篇
       

本站已停用滑鼠右鍵和各種快捷鍵,程式碼區塊內容可以直接在右上角點擊複製按鈕進行複製

zh_HK