MariaDB 實用主機架設指南

簡介

經過一點實驗後,我已經在 ContainerStation 中成功運行了最新版穩定版 MariaDB,並想分享一些學到的經驗。為了驗證部署是否成功,這個過程還包括以下步驟:

  • 建立一個專用服務用戶 backup,並為該角色設定有限權限

  • 透過 PHPMyAdmin 建立遠端連線

  • 建立測試資料庫並執行測試備份

  • 從測試資料庫刪除一筆紀錄並執行測試還原

  • 撰寫並測試用於自動化資料庫備份的腳本

  • 將腳本加入原生 QTS 排程器(crontab),實現全自動化

在這篇初始文章之後,你會看到一系列「回覆」,這些回覆會一步步帶你完成這個流程。

在閱讀之前,重要的免責聲明:我不是 QNAP 或 MariaDB 的員工,也不是專業的資料庫管理員(DBA)。我只是個對(Linux)命令列、使用 SSH 及嘗試新事物感到自在的中等程度技術人員。我並非接下來要討論的任何元素的專家,但我已經做過足夠的實驗,讓這一切都能運作。請在閱讀本指南時記住這一點——如果你發現錯誤或改進空間,回覆留言。還要記得,雖然以下內容在事實上沒有錯誤(因為我確實如描述般讓這一切運作),**但這並不代表本指南就是最佳做法。請將這份指南視為起點跳板,讓你有基本概念,並自行探索更深入的方向。當你在網路上閱讀建議時,你應該 永遠考慮資訊來源。

但在進入有趣的部分之前,我們需要先問並回答三個關鍵問題。第一個是:既然 QNAP 已經在 QTS 原生提供 MariaDB,為什麼我們還需要或想要在 ContainerStation 裡安裝它?這不是多此一舉嗎?

這是一個關鍵問題,必須認真思考,只有在有正當理由時才繼續往下。簡而言之,最可能肯定回答這個問題的三個理由如下:

  • 如果你在安裝時就知道未來需要將 MariaDB 實例移到其他硬體平台——因為匯出容器、帶到其他地方再匯入,比執行多次安裝、還要備份和還原一堆資料庫容易得多……

  • 如果你發現要部署在 MariaDB 上的應用程式,需要 QNAP/QTS 原生版本 App 所沒有的功能。(我就是這種情況——我開始使用 BookStack,它需要 utf8mb4 字元集,而 QNAP 目前支援的 MariaDB 版本(寫作時為 10.5.8)並未提供。)

  • 如果你的 NAS 並非執行生產或關鍵任務,且可以安全地進行實驗——而且你已經取得相關主管的同意,或有權執行這項工作。(我們接下來要做的事情本身並不危險,但謹慎總是好的。)

第二個問題是:除了使用 ContainerStation,還有什麼其他選項?

我查詢後,得出兩個主要替代方案:在其他主機上運行 MariaDB;或是不用 ContainerStation,改用 QNAP 的 VirtualizationStation。我不想偏離主題,但也認為有必要回應這兩個替代方案:

  • 我決定繼續在 QNAP NAS 上主機 MariaDB,因為它能提供資料完整性保護(RAID-6 卷;我的 NAS 由非常可靠的 UPS 供電),而且任何「第二主機」,不論是什麼,都會帶來更多硬體需要維護、另一個作業系統和軟體堆疊需要維護,當然還有更高的電力消耗。

  • 我確實有研究 VirtualizationStation,也很感興趣,會再進一步實驗。優點是 VS 可以讓我像是在獨立硬體上運作,卻沒有額外負擔——特別是能簡化 MariaDB 的備份/管理,讓漏洞管理和更新更有效率……缺點是,我可以用其他方式降低漏洞風險……而且 VSContainerStation 消耗更多 NAS 資源。

你的使用情境幾乎肯定會不同,甚至可能獨一無二——所以在投入部署這個解決方案之前,請確定它適合你。尤其要考慮在 ContainerStation 中執行程式碼時修補更新的複雜性。你的實作是否高風險?如果是,請仔細思考。

好了,如果我還沒讓你打退堂鼓……我們開始吧!

非常感謝您詳細的分享!我們的社群確實非常需要更多像這樣有幫助的貢獻。

我也會請我們的內部團隊根據您的設定進行測試。

再次衷心感謝您的付出與貢獻!

00a. 在開始之前——準備與警告

我們先來說明警告:

此處危險,請小心。

完整執行本指南將需要你透過 SSH 連線到你的 QNAP NAS(以及使用網頁管理介面),編輯本地基礎設施(特別是 crontab,可能還有本地共享資料夾),並且在 NAS 上部署與設定軟體。

如果你對於上述所有操作並非完全熟悉,請在此停止*。*

我已經測試過本指南中的所有步驟……這些步驟在我的個人環境下是可行的。為了讓說明更清楚,我在撰寫這些筆記時所使用的組件包括:

  • 一台 QNAP NAS——我用的是 TVS-672XT,運行 QTS 5.2.7.3256

  • 一台桌上型工作站——我用的是自組 PC,運行 Mint Linux 21.3

  • 一份 PHPMyAdmin 5.2.1——我是在 Raspberry Pi(4B)上運行
    (你完全可以用 MySQL Workbench 來取代 PHPMyAdmin——基本上你只需要一個客戶端來建立測試資料庫,並填入一個資料表和幾筆測試資料。)

  • 一個非「Admin」帳號於你的 QNAP NAS。你確實有一個用來處理所有基本 QNAP 管理工作的帳號,對吧?你不會什麼都用原廠「Admin」帳號吧……這樣萬一發生不可預期的問題,你可能會被鎖在 NAS 外面……只是提醒一下……

  • 一個固定 IP 位址。我們將會為 MariaDB 容器分配一個專用(固定)IP 位址。這是因為我們不希望 DHCP 租約到期後 IP 位址被更換,導致需要重新設定客戶端;當然也是因為我們希望能從網路上的其他主機存取 MariaDB,而不只是 QNAP NAS 本身。

00b. 在我們開始之前——資料收集需求

讓我們先問一個重要的問題:既然容器技術的核心理念就是容器映像檔是自給自足的,包含執行程式所需的一切;而且因此容器的邊界設計上就是不應被跨越,那麼*我們究竟要如何備份 MariaDB 資料?*目前我找到三個可能的答案:-

  • 你可以停止整個容器並將其匯出成 tar 檔——然後將這個 tar 映像檔納入傳統的(例如 HBS3)備份方案,或複製到另一台 NAS 或外接硬碟。這種方式非常可靠,但這也意味著你執行的所有資料庫在備份過程中都會無法使用——而且你擁有的資料庫越多、資料集越大,停機時間就會越長。

  • 你可以對正在運行的資料庫執行 mariadb-dump 指令(這樣花費的時間較少且產生的檔案較小),然後使用“docker cp”指令將匯出的檔案穿越容器邊界,複製到本機 QTS 檔案系統。這同樣可靠,且可能稍微快一點,但由於你會得到兩份備份檔(MariaDB 容器內部的匯出檔,以及 MariaDB 容器外部的匯出檔),除非你進行額外的清理,否則每個資料庫的“.sql”匯出檔所節省的硬碟空間可能會被抵銷。

  • 最後,你可以——在建立容器時,但僅限當時——建立一個邏輯且永久開啟的橋接,連接容器檔案系統與本機 QTS(NAS)檔案系統。這樣你可以像第二種方式一樣執行 mariadb-dump 指令,但匯出的檔案可以直接寫入本機 QTS 檔案系統,無需先在容器內建立本地副本再用“docker cp”跨越容器邊界。簡而言之,這是技術上最簡單的解決方案,但它會在兩個檔案系統之間建立一個永久開啟的“橋接”。

顯然,這個決定我無法替你做。但如果我們想採用第三種方式——這也是我個人的選擇——那我們就需要先取得已安裝 MariaDB 容器內部實際檔案系統的資訊——這樣我們才知道要在哪裡建立檔案系統的“橋接點”,而且我們必須在建立 MariaDB 容器之前就取得這些資訊!但要做到這一點,我們需要“進入”官方 MariaDB 容器內部——我找到兩種可能的方法,但只有一種成功。

沒成功的方法(你可以自行嘗試)是使用一個實作 Docker API 的腳本,藉此匯出映像檔。這裡有個連結,是我試過但沒成功的,這個腳本利用 Docker API 將 Docker 映像檔下載到本機檔案系統,不需要安裝 docker。也許你會比我更順利……

我的解決方式多幾個步驟,但簡單可靠:先從 docker 進行 MariaDB 的試裝;探索安裝後的映像檔以取得所需資訊;然後解除安裝映像檔,最後再以我們想要的參數進行乾淨安裝。

老實說,等你折騰完第三方腳本的各種小問題,你大概直接從 Docker Hub 進行一次“試部署”會更快。你自己決定。

請注意,一旦你用 ContainerStation 建立了容器,想要切換到第三種方式或從第三種方式切換,唯一的方法就是刪除並重新建立容器。所以請花點時間做出明智的選擇……

本指南接下來會涵蓋這三種方式,請在相關章節特別留意。

01. 選擇正確的 MariaDB 容器

你大概不會驚訝地發現,MariaDB 團隊針對他們產品支援的每個版本都有一個容器映像檔。這讓我們在開始之前,必須先回答三個重要問題:

  • 我們怎麼知道要安裝的 MariaDB Docker 映像檔是官方檔案,而不是被惡意修改的副本?

  • 我們是否真的 需要 安裝某個特定版本的 MariaDB?

  • 當我們決定好要哪個版本的 MariaDB 後,要如何告訴 ContainerStation 我們要哪個版本,才能正確部署?

第一個問題最容易回答:ContainerStation 預設會直接從 “hub.docker.com”——官方 Docker 儲存庫——拉取所有 Docker 映像檔。如果你不打算信任 ContainerStation 能可靠地做到這一點,那我很誠懇地建議你就此打住,因為這份指南無法處理這個疑慮。

第二個問題我無法直接替你回答,因為這完全取決於你的使用情境。不過,我可以分享一些小技巧。正如我們即將看到的,負責 MariaDB 映像檔的人員建立了兩個具有特殊名稱的映像檔,分別是 “mariadb-latest” 和 “mariadb-lts”,其中 “lts” 代表 “Long Term Support(長期支援)”。如果你需要使用最新穩定版本,或需要延伸支援的版本,應該選擇這兩個名稱之一。

要檢查特定(且官方!)MariaDB 映像檔的可用性,首先,在瀏覽器中開啟一個分頁,前往 “https://hub.docker.com/”。如果前述網址是可點擊的超連結,請務必再次檢查瀏覽器的網址列並檢視網站憑證,確認你是在官方 Docker 網站。進入後,你會發現有兩種方式可以找到我們需要的資料。

第一種是在首頁左側邊欄的 “Trusted content” 區塊,應該會看到一個名為 “Docker Official Images” 的連結。2025 年 11 月我點擊該連結時,會進入一個 “search results” 頁面,開頭顯示 “1 – 30 of 178 available results”——而 MariaDB 映像檔就在第 6th 列。或者,我們也可以直接用網站頂部橫向選單/導覽列的搜尋框,輸入 “MariaDB” 作為關鍵字。

你會發現 Docker Hub 上其實有多個不同的 MariaDB 套件(例如我看到 “mariadb”、“mariadb/maxscale” 等等)。我們需要選擇第一個,也就是 “mariadb”。這個很容易辨認,因為 logo 上的海豹是棕色的,而不是黑色輪廓;在 “mariadb” 名稱右側,會看到一個藍綠色的小花結和 “Docker Official Images” 標籤。撰寫本文時,這個項目的第一個中繼資料(“Pulls”)顯示它已被下載超過 10 億次。這就是我們要的套件。

點擊名稱後,連結會帶你進入一個頁面,裡面有這個 “主” MariaDB 映像檔所有不同發行版本的詳細資訊。在頁面標題下方,應該會看到兩個分頁:“Overview” 和 “Tags”。

如果預設沒有選中,請點擊 “Overview”,並注意有一塊超過 60 個超連結的區塊,標題是 “Supported tags and respective Dockerfile links”。仔細看,這個表格中應該總會有一個項目是 “latest”,另一個是 “lts”(長期支援)。請注意,如果你要找 “LTS” 版本,這個頁面上可能有三、四個名稱包含 “lts” 的版本。只有一個檔案名稱是單純的 “lts”,如果你用 “Ctrl-F” 搜尋,請一直按 “下一個” 直到找到正確的版本。根據你的需求,從這個頁面選擇並點擊其中一個連結——如果你需要特定版本,不一定要選 “latest” 或 “lts”。這個清單的排序方式是最新/前沿版本在最前面,較舊的版本則以時間倒序排列。(順帶一提,QNAP 目前支援的版本——10.5.8——已經被擠到清單底部……還好我們有 Docker 這個選項!)

撰寫本文時,我點擊 “latest” 會被導向 GitHub 頁面,裡面有該映像檔的原始 Docker 設定/描述檔。你可以在該頁面(瀏覽器按 Ctrl-F)用 “version” 作為關鍵字搜尋。如果一切順利,你會發現游標停在一個標題為 “# OCI annotations to image” 的區塊內——在這個區塊裡,你會找到類似以下內容的參數:

org.opencontainers.image.version=“12.0.2” \

由此可知,“mariadb:latest” 目前會安裝 12.0.2 版的資料庫。請記下這個資訊——稍後我們可以檢查是否如預期運作。**當然,**如果你需要/想要不同版本,也可以在前一個 DockerHub “Overview” 頁面挑選任何明確標註版本的替代方案,並用上述驗證步驟確認你選的套件描述檔與所需版本相符。我也應該提醒你,雖然網路上還有其他 Docker 儲存庫,ContainerStation 也允許你匯入已下載並快取在本地的容器,但我們一開始說要回答的問題之一,就是如何確保下載到合法程式碼而非惡意軟體。

這就是那個問題的答案:我們使用 ContainerStation 的匯入機制(它是“硬編碼”到 DockerHub),並且已檢查並確保即將從該儲存庫拉取官方 MariaDB 映像檔。

關鍵要注意的是,前述頁面上 “tags” 的**精確**文字,就是我們要提供給 ContainerStation,告訴它要安裝哪個 MariaDB 版本的參數。稍後我們會看到這要怎麼做。

02. 從 QNAP 應用程式商店安裝 ContainerStation

透過網頁管理介面存取您的 QNAP NAS。驗證身分後,找到「App Center」應用程式——它通常會釘選在桌面上,或者可以從「主選單」進入,在 QTS 5.2.7 的情況下,「主選單」會以三條橫線的圖示顯示在網頁管理介面左上角。

開啟「App Center」後,點選左側邊欄的「工具程式」,然後搜尋「Container Station」(預設情況下,每個分類中的所有應用程式都會按字母順序排列)。

點擊藍底白字的按鈕以「安裝」。

很簡單。

下載並安裝程式碼可能需要幾分鐘(取決於您的網路速度)。安裝完成後,啟動按鈕會從藍底白字「安裝」變成白底藍字「開啟」。

03. ContainerStation 首次啟動與資料卷選擇

免責聲明——這部分我無法給你明確的操作指引,因為你需要採取的具體步驟會取決於你所安裝 ContainerStation 的 QNAP NAS 的底層配置,以及在卷(Volumes)、LUN(邏輯單元,Logical UNits)等方面的設定方式。

重要提示: 如果你不確定 NAS 的配置,請在繼續之前,前往「控制台」,並在「系統」分組中尋找名為「儲存空間與快照」(Storage & Snapshots)的應用程式。在這裡,你應該可以看到 NAS 在首次加入硬碟並進行初始設定時所指定的底層配置概覽。以我為例,我只有一個卷,名稱很有創意,叫做「DataVol1」,它是一個由 6 顆 WD Red 12TB 硬碟組成的 RAID6 陣列。如果你檢查「儲存空間與快照」時發現列出的不只一個卷,我強烈建議你詢問設定 NAS 的人,他們希望你將「/Container」資料夾存放在哪裡。你需要考慮可能的資料占用需求,特別是我們即將安裝資料庫引擎,這可能會對儲存空間有很高的要求。在繼續之前,請務必確認你應該將「/Container」安裝在哪個位置。

點擊 ContainerStation 的圖示啟動程式。你應該會看到一個「歡迎」橫幅,底下有文字:

歡迎使用 Container Station

Container Station 將在 File Station 中建立一個名為「Container」的共用資料夾,預設用於儲存所有映像檔與容器。

在上述文字下方,你應該會看到一個組合[下拉]框,預設值為「/Container」,再下方有一個按鈕「開始」。我的 NAS 只設定了一個卷,所以我只看到這個選項[因為沒有其他選擇]。如前所述,如果你的 NAS 設定了多個卷,你在這裡一定會看到不同的選項。如果你屬於這種情況,很抱歉,你必須自行決定這部分。當你確認並設定好共用資料夾的位置後,點擊「開始」,讓腳本執行完成。

我想補充說明,在我的情況下,所選的卷是 NAS 的主要資料卷,因此 ContainerStation 可以隨需求擴充容量。這可能是好事,也可能有風險,這取決於你選擇在容器中運行的程式碼的可靠性,以及它是否可能消耗大量磁碟空間——例如,產生過長且沒有自動清理機制的日誌檔。請在決定部署「/Container」共用資料夾的位置前,仔細考慮你的用途。

以我為例,當我設定 ContainerStation 時,系統會詢問我是否同意將使用資料收集並傳送給 QNAP。這不是我能替你回答的技術問題。不過請注意,如果你的 QNAP 是公司所有,這個決定可能不是你能做主的。

好了,到目前為止,我們已經安裝並設定好 ContainerStation,目前是空的,但已可使用。啟動後,預設會看到名為「總覽」的首頁,內容包括容器、應用程式,以及 NAS 資源——CPU、記憶體及「CPU 使用率前五名」的容器。此時,這一切應該都很安靜。

04. 建立我們的 MariaDB 容器

在這個階段,我會假設你想要直接繼續建立一個 MariaDB 容器……但你可能會先有幾個問題。

  • 等等——為什麼我們需要 建立 一個容器?這裡的重點不是要運行一個預先建好的 MariaDB 實例嗎?

    好問題。我不是 Docker 細節方面的專家,但我基本的理解是,我們會先建立一個本地(空的)容器,然後用從官方 Docker Hub 下載的官方 MariaDB 映像檔來填充它。

  • 等等——我在{請插入你選擇的科技新聞網站}上讀到一篇報導,說高達 20% 的公開 Docker 資源庫中有充滿惡意軟體的映像檔——像是比特幣挖礦程式。我要怎麼知道你不是要引導我安裝你剛上傳的一堆惡意軟體?

    更好的問題。這代表你是以安全為導向的思維來看待這件事。答案其實很簡單——我們會告訴 ContainerStation 要抓取的映像檔名稱,但它會直接去預設的 Docker 資源庫,而不是要求我們指定映像檔的 URL。 透過這個機制,你應該可以有相當的信心我們拉下來的是正規的映像檔。

在 ContainerStation 視窗的右上角,你應該會看到一個白色文字配藍底的下拉選單,預設標籤是「Explore」。點擊下拉箭頭展開選單,然後你會發現第一個選項是「Create Container」。請選擇它。

這時會跳出一個名為「Create Container」的視窗,標示為 3 個分頁中的第 1 頁「Select Image」。在第一個分頁的主面板上有三個控制項——一對單選按鈕用來選擇 Basic 或 Advanced 模式,一個標示為「Registry」的下拉選單,以及一個名為「Image」的文字框。

首先,請將模式切換為進階(Advanced)。我們需要用進階設定來傳遞 MariaDB 啟動時的參數。當你切換模式時,你會看到「Registry」下拉選單被兩個新的單選按鈕取代,分別是「Docker image」和「LXD image」。請保持在「Docker image」(因為我們要部署的是 Docker 格式的檔案)。注意「Image」框內的灰色文字是 ‘registry/image:version’——而「:version」這部分非常重要,稍後會說明。

「Docker image」這個單選按鈕基本上是指示腳本使用 Docker Hub 作為映像檔來源,而「Image」文字框則是我們需要提供的參數,用來告訴安裝腳本要安裝哪個套件及其版本。

這裡就是我們填入之前在 Docker Hub 搜尋到的相關映像檔名稱的地方。例如,我這邊「Image」欄位填入的值是 mariadb:latest

然而,如果你運行的應用程式需要特定的版本,這裡就是你指定想要的版本的地方。例如,在撰寫本文時,網頁應用程式 NextCloud 支援的版本是 31.0.10,且其內部基礎架構驗證建議最佳運作於「MariaDB >=10.6 且 <= 11.4」。所以如果我要架設 NextCloud,我會填入「mariadb:11.4」或「mariadb:11.4.9」。

指定好你需要的版本之後,點選右下角的「Next」。這時安裝程式會短暫顯示「retrieving information」的提示橫幅——它正在驗證我們剛剛提供的細節,並到 DockerHub 搜尋該映像檔。

現在你應該會看到視窗從「1. Select Image」切換到「2. Configure Container」,並且我們有一堆新的欄位需要填寫。

第一個是**「Name」**。這是我們要給這個容器(運行在剛安裝好的本地「ContainerStation」環境中)的易讀名稱。這個名稱要稍微想一下——叫它「Xb17-123f」可能沒什麼幫助。如果這是你的第一個容器,但未來可能會有多個,我建議你可以考慮建立一個命名規則。以下是你可以納入結構化命名的一些元素:-

  • 容器內容——如果你會運行多種軟體堆疊——MariaDB、OpenLDAP、Jupyter、Plex、RStudio 等等,那你會想在名稱中包含「MariaDB」或類似字樣。

  • 容器用途——這是給程式設計師的[開發](Development)容器、用於預產測試的[測試](Test)容器、[正式](Production)環境,還是[備援](Contingency)或[備份](Backup)用於緊急情況的實例?用一個字母標籤可以讓你一眼就看出來。

  • 內容版本——如果你像我一樣,是為了取得比 QTS 內建更高版本的 MariaDB,那你可以把名稱調整為 MariaDB_P12-0-2 或類似格式。

  • 你可能會為特定應用程式部署專用容器——所以你可能會有一個專為支援單一應用的 MariaDB 容器,這時應用名稱也會出現在名稱中,如 MariaDB_NextCloud 或 MDB_NC。

  • 最後,請記住,不論你選什麼名稱,你都必須在 shell 提示字元下輸入這個字串到「docker」指令,告訴 Docker 你要操作哪個容器。所以不要取得複雜,因為你會輸入很多次。

俗話說,「你做你自己」,但請花點時間好好想一想。

接下來是**「Restart Policy」**——選項有「None」、「Always」、「On Failure」和「Unless Stopped」。預設是「Unless Stopped」,各選項的意思應該都很直觀。我選擇保留預設值。這裡有官方 Docker 文件連結,有興趣可以深入了解。

接下來是「Network Configuration」——這是一個很重要但容易讓人困惑的設定,所以我覺得值得多說一點。畫面上很有可能「Exposed」 ports 欄位已預設為「3306/tcp」且為灰色不可編輯,即使在頁面下方還有一個「Container Port」選項,也預設為 3306(MariaDB/MySQL 的預設 TCP 連接埠)。

這裡有個陷阱……如果你把這個值改成 MariaDB 的非標準連接埠,你還是可以啟動容器,但你幾乎無法從網路連接到你的資料庫。這是因為實際的 MariaDB 執行檔會用其他設定檔——這些檔案內嵌在容器映像檔中——可能不會理會你在這裡設定的值。[免責聲明——我就是這樣踩到的!] 請小心更改這個值——並參考下文說明如何檢查你的 MariaDB 實際啟動時監聽的連接埠。只要你有給容器分配專屬 IP,並且用 MariaDB 預設的 3306 埠,基本上不會有問題。

先不要點「Next」——還有事情要做……

05. Advanced Container Settings

Before we leave this page, we need to dig a bit deeper. Click on “Advanced Settings”, which you will find below the “Network Configuration”.

In this lowest level of detail, you should find a page broken down in to 7 vertically stacked tabs, named: Commands, Networks, Environments, Labels, Storage, Runtime and Resources.

Let’s now work through each of these in turn:-

Commands
Leave the “Command” and “Entrypoint” text boxes in their “default” settings, and make sure that the “Allocate interactive processes (-i) for the container” and “Allocate TTY prcoesses (-t) for the container” are both set to active. We are going to rely on these two parameters being set ‘on’ when we come to set up and manage the container once it’s running.

Networks - IMPORTANT
In my case I wanted to access this container via the default [10Gb] network port on my NAS… but if you have a model with multiple network ports and connections, this is where you can specify which of the network ports on your NAS that your Docker container should be visible to your network.

The “Preparation and Warning” notes at the beginning of this guide included a requirement for a static IP address, valid on the local network – and this is where that value will be used.

Change the ‘Network Mode’ radio button selector from “Default (NAT)” to “Custom”. Allow the drop-down Combo Box to remain in “bridge”, then scroll the window down to reveal a couple of additional parameters tucked away at the bottom.

One of these is a check-box with the label, ‘Use a static IP address’. Activate that check-box and the installation window will change to give a 3-row data box with ‘IP address’, ‘Subnet mask’ and ‘Gateway’ as labels for the 3 rows. You will hopefully find that the Subnet mask and Gateway are pre-populated and greyed out – this data is sourced from the main network configuration parameters of your NAS. You should also find out that some of the 4 digits of your IP address – specifically the network address portion are also pre-defined and greyed out. In my case I am using a Class B network with network address 172.16.0.0, so I have just 2 parameters to fill in. Update the values in the “IP address:” parameter to match the address you previously obtained.

{{ Edit to Notes - Added April 3rd, 2026 }}

There’s a non-obvious but critical consequence of the decision you make here regarding whether to explicitly identify IP Addresses for DNS Servers or whether you are happy to allow the container to simply adopt the default DNS values set at your NAS/host level.

Suppose there is a future time where you need to make changes to your local DNS infrastructure and further suppose that those changes require you to amend the IP addresses for your DNS Servers on your network. If you create a new container with the DNS Server IP addresses set to “NAS Values”, then when you need to come to change to a new DNS host IP address, the only way you can do this is at the Host NAS Level. Under the hood, Docker provides a DNS proxy service to running containers. It uses a hidden IP address (127.0.0.11) and the DNS resolver details in containers will be set to this value.

The consequence here is that if you use “host based DNS” in this way, then when you come to change your DNS host value, you have given yourself no option except to migrate ALL your containers at the same time.

Conversely, if you explicitly set your DNS Server IP Addresses manually at this step in the process, then you grant yourself the ability to migrate “one container at a time” to a different IP address, and/or set different containers to use different DNS Servers [should you have that requirement].

The catch here - something that is not obvious at container creation time, is that once you create your container, your DNS decisions are “hard-coded” and cannot be changed.

Does this matter? Well, only you can answer that question. But if, say, you have a mix of “Production” and “Test” containers running in a single Docker instance [which, if you’re limited with respect to hardware, is a perfectly reasonable approach], then you’re going to be forced to migrate both test and production environments at the same time. That seems a bit counter-intuitive.

Take a moment to ensure that you have this configured in a way that is appropriate for your environment and make sure to document what you have done and why.

{{ End of Edit }}

Environments – CRITICAL
You can think of this element as for the specification of environment [run time] variables that the container is going to pass to MariaDB as/when MariaDB starts up. The values of these variables are essentially secure – as they are only visible here and inside the container itself, but they are critical.

That’s because you must provide a root password to the docker image of MariaDB as part of the initial configuration. To do this, click the “Add New Variable” button at the top right corner of the page in this tab. The name of the environment variable we have to create is “MARIADB_ROOT_PASSWORD” and the value we select should be something that conforms to conventional password rules. If you miss this step, your Container will not start. [OK, disclaimer. I just exaggerated when I said that you must provide a root password here. That’s not strictly true. One of the other support options is “allow no password”. I chose to write the instructions as I did above because I don’t want to encourage anyone to do anything that is insecure. The right action to take here is to use a generator to produce a secure password and use that. Please take a moment to reflect on the sensitivity of the data your DB will host and the environment in which your NAS operates. As I’ve noted before: “You do you”.

Labels
We’re going to leave the settings of this tab to their default values

Storage – IMPORTANT
In the section of this document with the title, “00b. Before We Get Started – A Data Gathering Requirement”, we considered the question of whether or not we want to create a permanent connection between the container’s internal file system and that of the NAS itself. This is where you get to decide which approach you will take.

If you’re currently performing a “pre-install” for “Option 3”…
– that is to say, deploying the MariaDB container so that you can jump in and have a look around, so that you know where to make a connection to your NAS file system, or if you’ve decided that you want to keep your MariaDB container completely isolated, you can skip Storage and leave it blank – simply jump down these notes to “Runtime” and continue.

If you’re currently performing the “second/full/final install” for “Option 3”…
– and/or you have otherwise determined the location of a folder within the MariaDB container that you wish to permanently “bridge” to the QTS file system, this is where you make that configuration. Please note: you can only make this decision at installation time – once “built” you cannot go back and edit this part of your container’s configuration. Whatever you decide here will be “final” for this particular container.

After selecting the “Storage” tab, click the “down arrow” to the right of the button labelled “Add Volume”. A pop-up window should appear below the button with three options in it – “Add Volume”, “Add Volume from Container” and “Bind Mount Host Path”. Select “Bind Mount Host Path” and note that a second “bind pair” appear in the main section of the window. This one will be differentiated with a small yellow “folder” icon – which signifies that it related to a folder native to QTS on the NAS. Click on the yellow folder icon and use the window which shows a path to actual, existing folders on the host NAS file system. Navigate through the file system until you select the remote endpoint that you want to be able to connect to from within your container. Ideally, you should make sure that the folder you select is part of an existing backup regimen – for example is enrolled within one of your existing HBS3 backups. Of course, you don’t need to have the QTS folder enrolled in an HBS3 backup before you add a MariaDB container, it’s just that if you want your exported .sql files to be archived, including the destination QTS folder in an HBS3 backup is the simplest way to do it.

Click in to the final data field, “Container:” and provide the path name to the location within the container on which we wish to mount the remote file system. (For users familiar with the soft-link operation of Linux, using the command “ln -s”, this is effectively the same thing). In our case, because our future selves were so helpful, we know that the internal folder we want to use is /var/backups. [Warning: if you’re reading this and preparing any version of MariaDB that is not 12.0.2, you really should be ignoring this hint and performing your own pre-install to check. Just saying].

Runtime
This tab controls the way that ContainerStation will spawn threads that execute the code in containers. Because ContainerStation is designed to operate three different types of container, this tab allows an administrator to help ContainerStation better understand how to interact with the executable code within. As we’re using a Docker image, we can let this remain with default values.

Resources
This tab allows you to decide whether you want to apply “upper limits” to the amount of hardware resource you are willing to allow this specific container to consume. It is likely to be very useful on larger NAS units and those with many users, because you probably don’t want one container to draw down all the available performance of the NAS. However, since this is going to be specific to your operating environment, there is no easy or obvious suggestion to make here. MariaDB recommend a minimum of 1Gb of RAM for basic operations. Stipulating CPU limits is going to be much harder, because different NAS models will have different CPUs installed.

If in doubt… either seek advice from an administrator, or try this as a rule-of-thumb… If you switch to “Limited” for any of the 3 options, the range of values will be pre-set based on your local hardware. Have a think about the range of users, workload and other applications running on the NAS in question and think about how much of the available performance you would be comfortable allocating to this one solitary container if it was “working hard”. In my case – a TVS-672XT used as a “home office” hub, I set limits at 25% of available resources across the board – and that has proven to be more than enough. Doing so gives me the confidence that even if my MariaDB container were to “go sideways” with a looping process, it will not kill my entire NAS – and, crucially, it will leave me with enough capacity/bandwidth to get in and figure out what is going wrong.

When you’re ready, click Finish.

In the background, ContainerStation will now download the “Mariadb:Latest” image from Docker Hub and then apply the various configuration parameters that we specified during the “create” process.

If we switch from the “Overview” tab of ContainerStation’s main display to “Containers” [via the left-side gutter margin], we should now see a single row in the main panel of the page, with a “Type” value of “Docker”, a “Name” value that matches the one provided earlier, and additional parameters – “Status”, “Application”, “Image”, “IP Address”, “Created On” and “Actions”.

At the bottom of the display we should also see a pair of tabs, “Logs” and “Status”.

If everything went [reasonably] well, then in the “Status” column of the table of containers, we should see a circular green icon and “Running”. Earlier in these notes, I mentioned that there was a way of checking to find out which TCP port our Docker instance of MariaDB was listening on – and this is it. Click on the “Logs” tabs and you should see a window with a black background and fairly small white text. Directly above the top right corner of this text window, you’ll see a small icon that looks like a square with an arrow pointing out of it towards the top, right corner. Click that arrow and the log window will expand to fill your browser. Unfortunately the content of this window isn’t rendered as HTML, so you can’t use “Ctrl-F” in your browser to search for the active port, but it should not be hard to find. In my case, the log contains the following:-

2025-11-06 7:59:15 0 [Note] Server socket created on IP: ‘0.0.0.0’, port: ‘3306’.
2025-11-06 7:59:15 0 [Note] Server socket created on IP: ‘::’, port: ‘3306’.

As I noted previously, when I tried to change the port via the Container setup options, I found that the value here remained stubbornly at port 3306. Eventually, I decided it wasn’t an issue since I was of course using a dedicated, static IP address and this was the only service the address would be likely to host. But I did say I would show you how to confirm the port that your MariaDB daemon is listening on and, well, this is it.

But: congratulations! You’ve just configured and installed MariaDB in Container station!

And it is currently absolutely useless!

Right now, all we’ve done is get the package downloaded and installed and got the main binary to successfully start executing. However, by default MariaDB won’t allow network connections and is supplied with just a single root/admin user. Now we need to perform a couple of very simple validation tests. The first is a simple network visibility test – just open a command prompt or shell prompt (from your workstation) and then issue the command,

ping {IP address}

where the {IP address} is the one that we applied to the container in the “Networks” tab of “Advanced Settings” and was based on the static IP address we obtained at the start of this guide. If we got our networking setup correct, we should see ICMP Echo packets returned to our workstation.

The second test, which is very helpful if you have the means to run it, is to perform an nmap scan. Nmap is a port scanning utility that can access a remote host and tell you whether or not the host is offering service for particular ports, such as TCP sockets. If your workstation is Windows based, you can download the nmap utility direct from the official Nmap web site . If your workstation is unix based, such as one based on GNU/Linux, you can almost certainly add the nmap utility direct from your local package manager.

Once you have the utility installed, simply check your container’s IP address. For example, I assigned the IP address 172.16.101.201 to my MariaDB container and when I run nmap against that IP address, this is returned:-

$ nmap 172.16.101.201
Starting Nmap 7.80 ( link to official nmap web site normally appears here ) at 2025-11-06 08:25 GMT
Nmap scan report for 172.16.101.201
Host is up (0.00012s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
3306/tcp open mysql
Nmap done: 1 IP address (1 host up) scanned in 0.08 seconds
$

In this case I have only one open/active port at the IP address, but it shows that TCP Port 3306 is open (which means that a listener is monitoring the network stack and will respond to packets with that port ID) and we can also see that the listener is “mysql” – which is what we want.

This gives us a good level of confidence that our MariaDB engine is at least installed and running.

06. 通過 SSH 存取 Docker

熟悉 MariaDB 的人都知道,它遵循「安全設計」原則,這意味著在首次啟動時,它只有一個已註冊的使用者,且不允許遠端(即網路)存取。我們不僅需要透過本地主機來正確設定它,還需要從 其 Docker 容器內部 進行存取。

讓我們開始吧。

首先,開啟一個 Secure Shell(安全殼層,SSH)連線到你的 NAS。你可以用多種方式來做到這一點——例如,Windows(透過命令提示字元)和 Linux(透過終端機)都可以直接輸入以下指令:

SSH {你的 NAS IP 或 DNS 名稱}

另外,你也可以使用像 PuTTY 這樣的客戶端應用程式——這是一款適用於 Windows 和 Linux 的免費 SSH 與 telnet 客戶端。選擇你喜歡的方式。當你登入並進入 \[NAS\] shell 提示字元後,輸入以下指令:

docker ps

你通常不需要在這個指令前加上「sudo」,但這可能取決於你用來存取 NAS 的非管理員帳號權限。執行這個指令後,你應該會看到兩行回應,包含一些基本資訊,標題分別為「CONTAINER ID」、「IMAGE」、「COMMAND」、「CREATED」、「STATUS」、「PORTS」和「NAMES」。

標題下方的那一行細節就是我們剛剛建立的容器。請記下「NAMES」欄位下的項目——這就是我們要與 MariaDB 實例互動時所需的特定容器名稱。它應該與你最初建立容器時所設定的名稱相符。

07. 存取 MariaDB 的檔案系統以尋找資料夾連結的端點
如果這是你第一次安裝 MariaDB,而且你的目的就是要找出容器檔案系統中哪個資料夾節點可以作為上述 Storage 設定的參數,那麼取得你需要的資訊其實非常簡單。首先,我們需要啟動一個互動式 bash(shell)工作階段,跳進容器內部。你需要透過連線到 NAS 的 SSH 工作階段輸入一條 Docker 指令。由於這種方法是你與 Docker 互動的常見方式,我們花點時間來拆解這條指令並了解各個元素的意思。在輸入之前,請先閱讀以下說明:-

sudo docker exec -it {yourContainerName} /bin/bash

在上述指令字串中:-

sudo - 告訴 NAS QTS 作業系統我們要用超級使用者權限執行接下來的指令。

Docker - 告訴 sudo 我們要用權限呼叫 docker 指令

exec - 是 “Docker Execute” 的縮寫,告訴 Docker 我們要執行一個可以在容器內找到的可執行程式

-it - 是參數旗標,分別代表互動模式(i)和終端機格式(t)。

{YourContainerName} - 如果我們在這個 Docker 實例中部署了多個容器,就需要這個參數。這樣才能告訴 Docker 處理器我們要操作哪個容器。

/bin/bash - 是容器內部可執行程式的完整路徑名稱。對於不熟悉 unix 家族作業系統的讀者來說,“bash” 是 “Bourne Again Shell” 的縮寫,是最早 unix 指令列環境之一(Bourne Shell)的延伸。

當你執行上述指令後,你會發現 shell 環境的命令提示字元改變了。它應該會變成類似這樣:-

root@{12-digit-hexadecimal-number}:/#

這個看起來奇怪的 12 位元十六進位值,當然就是 ContainerStation 在建立過程中分配的唯一容器 ID。現在我們已經進入 MariaDB 容器內部了。我們需要搞清楚目前在容器的哪個位置,以及該位置有哪些內容。我們將執行一個列出檔案的指令,並加上參數要求所有檔案詳細格式(這就像請 Windows 檔案總管顯示資料夾的「詳細資料」檢視)。依慣例,我們會進入容器的最上層「根目錄」(“/”)。請執行 shell 指令:

ls -al

你應該會在容器根目錄看到大約 24 個項目,前三個分別是 “.”、“..” 和 “.dockerenv”。接下來我們需要在這個檔案系統中搜尋一個可以作為容器與 NAS 檔案系統橋接點的位置。

往下掃描,找到一個名為 “var” 的資料夾。這個名稱是 unix 的三字母縮寫,代表 “variable”(可變),表示這個資料夾的內容預期會隨時間變動。這正好符合我們的需求,因為它用來表示資料儲存區。請輸入以下指令進入該資料夾:

cd var

切換目錄var)然後再次列出內容:

ls -al

此時你應該會看到第一個資料夾是 “backups”。請用

cd backups

進入它,然後再列出一次

ls -al

你會發現它是空的,這正是我們想要看到的結果。這非常理想——正是我們要找的資料夾。我們將用這個資料夾作為從 MariaDB 資料庫備份的橋接點。我們不需要做任何更動,事實上現在要離開容器 shell,請輸入

exit

指令。當你這麼做後,命令提示字元應該會變回 QNAP 的預設狀態。此時,我們可以切換回瀏覽器工作階段,回到 Container Station,如果需要的話點選左側邊欄的「容器」選項。接著可以找到我們剛剛建立的「MariaDB」容器。在「動作」欄點選齒輪圖示會跳出一個視窗,從中可以選擇「停止」,或必要時選擇「強制停止」。容器停止後,往下捲動視窗底部,選擇「移除」來刪除容器。移除完成後,我們就可以重新開始流程,因為現在已經確定好要在哪裡橋接容器檔案系統與 QTS 檔案系統了。

08. 通過 Docker 存取 MariaDB 的命令列介面

假設你已經完成了前面的步驟,現在擁有一個正確設定的容器,並且已經建立了容器與 QTS 檔案系統之間所需的資料夾連結。既然我們已經能夠「看到」我們的容器,接下來就要進入容器中的 MariaDB。我們會再用一個 Docker 指令來達成這個目的,但就像之前一樣,讓我們逐步拆解這個指令,讓你明白每個步驟的意義。請記住,如果你還沒這麼做,必須先「exit」離開容器,回到 NAS QTS 作業系統的提示符號,再執行下一步。接下來要用的指令語法如下:

sudo docker exec -it {yourContainerName} mariadb -p{rootPassword}

這個指令的拆解如下:

docker exec - 我們要讓 Docker 在容器內執行一個可執行檔

-it - 我們要以 (i)nteractive(互動)和 (t)eletye(終端機)模式執行

mariadb - 我們要 Docker 執行這個特定的二進位檔案

-p{rootPassword} - 我們要將這個密碼傳給執行檔——這就是我們先前在 Environment 變數中設定的密碼。

你會注意到我們沒有特別指定 UserID——預設會是「root」,也就是主要的管理者帳號。

執行這個指令後,應該就能進入 MariaDB CLI(命令列介面)。我不會詳細說明如何設定這個全新的 MariaDB 實例,部分原因是你可能會有自己的本地設定指南,另一部分原因是具體內容完全取決於你想用 MariaDB 來做什麼。不過,基本原則應該很簡單:

  • 採用「最小權限」原則——授權時避免使用萬用字元。

  • 特別是在允許「網路存取」時,不要單獨指定「%」作為「Host」(這會允許來自**[任何]**主機的存取),而是要配合你的網路位址使用萬用字元,限制只允許本地網段(或部分網段)存取。例如,我的本地 IP 網段 是 172.16.0.0,子網路遮罩為 255.255.0.0,所以我會將 Host 設為 172.16.%.%。這樣就只允許我從本地網路存取 MariaDB,其他地方無法存取。

  • 你最需要做的事,就是建立一個非 root 的 MariaDB 帳號,讓它有權限從你的(PHPMyAdmin / MySQL Workbench)主機存取資料庫,並賦予該帳號建立新資料庫的權限。

此外,無論你還會怎麼設定新的 MariaDB 實例,我都強烈建議你另外建立一個專門用來備份資料庫的唯讀帳號。如果你想這麼做,以下指令可以達成。首先,讓我們建立一個綁定到 loopback IP 位址的使用者:

CREATE USER ‘backup’@’127.0.0.1’ IDENTIFIED BY ‘{securepassword}’;

輸入上述指令時,請注意你提供的密碼要用單引號括起來,不要用大括號(除非你真的想把大括號也當成密碼的一部分!)。所以如果你的密碼是「password」,你應該這樣寫:

IDENTIFIED BY ‘password’;

接下來,給這個使用者授予「SELECT」任何資料庫的權限:

GRANT SELECT ON *.* TO ‘backup’@’127.0.0.1’;

這有助於你理解權限授予(grant)的語法。這裡,「SELECT」是授予使用者的權限,「ON *.*」則告訴 MariaDB 要對 pipeline 所有本地資料庫授權。這是一種特殊的授權方式——它不僅會授權現有的所有資料庫,還會自動對未來新建的資料庫授權。

不過,「SELECT」並不是備份用戶所需的唯一權限,下面我會列出我所用的權限。明確說明,這份清單來自 官方 MariaDB 文件。完整清單如下:

SELECT, RELOAD, PROCESS, SHOW DATABASES,

LOCK TABLES, SHOW VIEW, EVENT, TRIGGER

我們已經給了備份用戶「SELECT」權限,現在你只需要針對上述每個 MariaDB 指令權限各自重複一次「GRANT」語句。總共 8 個權限,如果每次只授予一個權限,就要重複執行 8 次。

將「backup」帳號設為 @’127.0.0.1’,就限制了這個帳號只能在本機伺服器上使用,例如用 crontab 等排程工具執行備份腳本。這是很基本的安全措施。即使有人發現了這個帳號的密碼,也無法(遠端)存取並竊取你的所有資料。

在結束本節之前,還有幾個很實用的命令列語句值得記住:

SELECT user,host FROM mysql.user;

以及

SHOW GRANTS FOR ‘{user}’@’{context}’;

例如:

SHOW GRANTS FOR ‘backup’@’127.0.0.1’;

如同語法所示,這會列出該使用者已被授予的所有權限——你可以用這個來確認你的用戶是否有足夠的權限執行本地備份。

請注意: 當你走到這一步時,很容易「作弊」直接下這樣的指令:

GRANT ALL PRIVILEGES TO *.* FOR ‘{yourUser}’@’%’;

(這會讓你從任何地方都能做任何事)但請記得這有多危險。一般原則是:只授予需要的權限。當權限不再需要時,立刻移除。

話雖如此,建立一個有廣泛權限、可遠端存取伺服器的互動用戶也是個好主意,但僅供緊急情況下使用,不作為日常或永久用途。如果你決定建立這樣的帳號,也可以用它來驗證接下來的步驟。

09. 從 PHPMyAdmin 存取 MariaDB

儘管 PHPMyAdmin 的介面略顯過時,但它是一個功能強大的工具,完全能夠透過網頁介面遠端管理 MariaDB 資料庫。由於其高度的靈活性,新增 MariaDB 伺服器的方式有很多種——例如,可以將細節新增到預設的 “config.inc.php” 檔案中,或是為單一 MariaDB 伺服器新增專用的第二個設定檔。

以我的情況來說,我選擇了最簡單直接的方法,將第二台遠端伺服器的細節加入現有的設定檔,如下所示(取自我的 config.inc.php 檔案):-

$i = 0;
/

  • 第一台伺服器 - MariaDB 5.5.68 on TVS-672XT
    /
    $i++;
    /
    認證類型 /
    $cfg[‘Servers’][$i][‘auth_type’] = ‘cookie’;
    /
    伺服器參數 /
    $cfg[‘Servers’][$i][‘verbose’] = ‘TVS-672XT - MariaDB 10.5.8’;
    $cfg[‘Servers’][$i][‘host’] = ‘172.16.101.2’;
    $cfg[‘Servers’][$i][‘port’] = ‘3307’;
    $cfg[‘Servers’][$i][‘compress’] = false;
    $cfg[‘Servers’][$i][‘AllowNoPassword’] = false;
    *

/

  • 第二台伺服器 – MariaDB 12.0.2 透過 ContainerStation 運行於 TVS-672XT
    /
    $i++;
    /
    認證類型 /
    $cfg[‘Servers’][$i][‘auth_type’] = ‘cookie’;
    /
    伺服器參數 /
    $cfg[‘Servers’][$i][‘verbose’] = ‘TVS-672XT - MariaDB 12.0.2’;
    $cfg[‘Servers’][$i][‘host’] = ‘172.16.101.201’;
    $cfg[‘Servers’][$i][‘port’] = ‘3306’;
    $cfg[‘Servers’][$i][‘compress’] = false;
    $cfg[‘Servers’][$i][‘AllowNoPassword’] = false;
    *

從這些參數和值可以看出,我的設定要求每次開啟 PHPMyAdmin 連線時都必須輸入使用者 ID 和密碼進行認證;然後透過瀏覽器 Cookie 保持我的連線狀態。

眼尖的你可能會注意到我的 “第一台伺服器” 使用的是 3307 埠口,而不是 3306。這是因為當我安裝 MariaDB 10.5.8 時,NAS 上已經有一個 MariaDB 5.x 的實例在運行——QTS 會自動偵測並避免埠口衝突,於是將第二個 MariaDB 服務的埠口從 3306 增加到 3307。

如果你已經有一個運作中的 PHPMyAdmin 實例,修改預設設定檔(或新增第二個設定檔)後,只需在你的網頁主機上執行本地對應的指令:

sudo systemctl reload apache2

即可啟用新的設定,確保 PHPMyAdmin 網頁應用程式已經更新其執行時設定。

打開你的瀏覽器(或新分頁),輸入你的 PHPMyAdmin 實例網址。如果你的 ContainerStation 映像是唯一的遠端伺服器,只要輸入剛剛建立的使用者 ID 和密碼即可存取。

如果你已經將 ContainerStation 實例新增為第二台遠端伺服器,你會在登入視窗看到一個下拉選單,可以選擇要管理哪一台遠端伺服器。下拉選單中顯示的描述會取自你在 “config.inc.php” 腳本中 “[‘verbose’]” 這個環境變數所設定的值,如上所示。

預設情況下,PHPMyAdmin 會帶你進入目前選擇的伺服器的 “伺服器首頁”。在畫面左側的邊欄應該可以看到已建立的資料庫。由於這是全新的 MariaDB 實例,應該只會看到:“information_schema”、“mysql”、“performance_schema” 和 “sys”。

此處需要特別檢查的重要元素,是在頁面右側名為 “Database server” 的區塊中,你應該可以找到 “Server version” 這個屬性。

我從已部署的 Docker 映像中看到的具體值為

12.0.2-MariaDB-ubu2404 - mariadb.org binary distribution

對我來說,關鍵的部分是 “12.0.2”——因為這證實了映像運行的是我想要的 MariaDB 版本。不過,注意 “mariadb.org” 這個元素也顯示了 docker 映像的來源。雖然這未必足以保證它就是正宗的 MariaDB 映像,但我們在每個步驟都很謹慎地檢查其真實性。

10. 建立測試資料庫

當我們登入 PHPMyAdmin(或 MySQL Workbench,或你正在使用的其他工具)時,我們將建立一個資料庫,並在其中新增一個包含幾筆紀錄的資料表。

由於我無法預先知道你使用的是哪一套工具,所以這裡不會提供詳細的操作說明。我選擇將我的資料庫命名為「demo」,資料表命名為「demotable」,並在其中建立了兩個欄位:「demokey」,這是一個自動遞增的主鍵;「demotext」,這是一個簡單的文字欄位。你可以依自己的需求命名。

接下來,我們需要在這個資料表中新增一些實際的資料。請務必建立至少兩筆紀錄。既然我們建立的是簡單的文字欄位,你應該可以直接輸入如下文字:

This is the first test record
This is the second test record

我們將使用這個資料表來測試備份流程。建議你可以使用 PHPMyAdmin 的「瀏覽」功能來查看這些紀錄,確認每筆紀錄中的文字都能清楚顯示。

當你確認紀錄已建立(在 PHPMyAdmin 中,你只需點選「瀏覽」分頁,當你在左側選單選取資料表後,這個分頁通常會在最左邊)。如果一切正常,我們就可以進行資料庫備份了……

11. 備份容器化的 MariaDB 資料庫

dedicated to your NAS 的 SSH 連線。連線後,我們可以執行以下指令的變體,根據我們設定的資料庫、輸出資料夾及使用者名稱進行調整:-

sudo docker exec -it {YourContainerName} mariadb-dump -h 127.0.0.1 -P3306
-u {yourBackupAccountName} -p{yourBackupAccountPassword}
–databases {yourDatabaseName}
–result-file /var/backups/{yourDatabaseName}.sql

以下是此指令中所用變數的說明:-

-it - 指定指令需以互動式文字介面(teletype)執行

{yourContainerName} - 為你在建立容器時指定的名稱

-h 127.0.0.1 - 指示 mariadb-dump 指令在本機(loopback host)執行。更重要的是,這符合我們設定「backup」使用者的方式。還記得我們是如何建立「backup@127.0.0.1」這個帳號的嗎?這就是原因……基本上我們將把這個指令包裝成一個腳本,並可透過自動排程執行——我們同時設定這個指令及執行它的使用者權限,只能直接由主機 NAS 執行。即使有人知道「backup」帳號及其密碼,也無法利用這些憑證在此環境下存取資料庫。最小權限原則……

-P3306 - 指定 MariaDB 實例所使用的 TCP 埠號

-u {yourBackupAccountName}

  • 這是已設定好、具有備份目標資料庫存取權限的 MariaDB 帳號名稱。以我的範例來說,你只需填入「backup」這個使用者名稱。

-p{yourAdminPassword}
這是你在建立該帳號時於「IDENTIFIED BY ‘…’;」參數中設定的密碼。重要提醒: 如果你沒注意到,「-u」與使用者名稱之間可以有空格,系統會忽略,但「-p」與密碼之間若有空格,空格會被視為密碼的一部分,導致驗證失敗!

–databases {yourDatabaseName}
[請注意「databases」前有兩個連字號!] 這裡我們只會提供一個資料庫名稱作為測試(如「demo」),老實說我建議你永遠這樣執行。多次執行指令很簡單——而且保持指令簡單可以減少錯誤。

–result-file /var/backups/{yourDatabaseName}.sql

[請注意「result-file」前有兩個連字號!] 此參數中的「/var/backups/」對應於我們在 MariaDB 容器(v12.0.2)內部探索並驗證過的資料夾結構,而我們指定的檔名應該能清楚代表正在歸檔的資料庫。

加上 .sql 副檔名不是必要的,但這是一個有用的慣例,有助於從檔名辨識檔案類型。

你很可能會被要求輸入你的帳號密碼,以便在 NAS 上執行 sudo 指令——這是 unix 類主機使用管理員功能的標準做法。輸入後,如果你每個步驟都正確,應該會看到 shell 提示符返回且沒有錯誤。一般規則——如果錯誤,請回頭仔細檢查每一步。

我們需要檢查備份是否如預期執行。如果你如本指南所述建立了檔案系統橋接,那麼你不需要再次進入 MariaDB 容器,執行:-

sudo docker exec -it {YourMariaDBContainerName} /bin/bash

因為你剛建立的檔案應該會顯示在你指定的目標資料夾。如果你選擇不建立橋接,請如上所述重新進入容器,並切換到預設的輸出目錄:-

cd /var/backups

然後列出該資料夾內容:-

ls -al

如果一切順利,你應該會看到一個檔案,時間戳記非常新,檔名為 {yourDatabaseName}.sql

如果有,恭喜你!如果沒有,請仔細回顧前述步驟並再試一次。

最後,當你位於包含備份的資料夾時(無論是在容器內或透過 Secure Shell 連線到你的 NAS),執行以下指令:-

cat {yourDatabaseName}.sql

這會將檔案內容顯示在螢幕上,你應該會看到「demo」資料庫的內容,包括你建立的資料表及兩筆文字資料。請務必確認這兩筆紀錄確實存在於此檔案中。因為,很快我們就會刪除其中一筆,然後用這份備份來還原資料……

11a. 通過容器牆匯出備份檔案

如果你已經透過 Storage 參數使用資料夾橋接方法,讓你的容器可以存取 NAS 檔案系統,那你已經準備好,可以跳到下一步。然而,如果你沒有建立這個連線,你就需要將 .sql 備份檔案複製到容器外部,以便在還原過程中使用。

好消息是,這其實非常簡單,只需要一條指令。

在你的 NAS 的 Secure Shell 提示符下,輸入你專屬版本的以下指令:

sudo docker cp {YourMariaDBContainerName}:var/backups/{yourDatabaseName}.sql /share/NFSv=4/Public/Backup/

在 “.sql” 和 “/share/NFS” 之間應該只有一個空格——或是你 QNAP NAS 的相對本地路徑。另外,你應該將 “/Public/Backup” 替換為相關的共享資料夾名稱,以指定你希望檔案放置的位置。

這條指令的作用——手動——是建立你的匯出/傾印檔案的副本,並將副本放在 NAS 檔案系統中你自己可見的區域,因此也可被 HBS3 備份。

請注意: 這也意味著你現在有份資料庫——原始檔案和兩個傾印檔案。對於小型資料庫來說這不是問題,但如果你管理的是非常大型的資料結構,可能會變得麻煩。

到目前為止,我們已經完成了備份流程的三個階段中的兩個階段,這是達到充分備份結果所需的。最後一個階段,當然,就是將目的資料夾(“/Public/Backup”)納入正式的資料管理流程,例如原生 QTS 工具 HBS3。

另外——如果你的資料庫檔案很大,並且你使用“檔案複製”流程將 .sql 匯出檔案放到 MariaDB 容器外部,那你應該考慮額外的幾個步驟。在你的最終/最重要的備份作業執行完畢後,應該再設定一個作業,移除你放在 MariaDB 容器內 /var/backups 的中間 .sql 檔案。如果你使用 HBS3 作為備份機制,該工具無法執行額外指令,也無法觸發外部批次作業。

我想到的方法是,將 HBS3 設定為定時執行,然後再用 crontab 設定定期執行 shell 腳本,時間安排在 HBS3 作業結束之後。請注意,這並不完全安全——因為“清理”腳本即使在 HBS3 作業失敗時也會執行……

12. 驗證 MariaDB 還原

我們剛剛成功建立了 “demo” MariaDB 資料庫的完整備份。如果備份輸出寫入到了 MariaDB 容器內的某個位置,我們也使用了第二個指令,將備份從 MariaDB 容器內提取出來,並放到我們可以用更強大備份機制保護的位置。

但這份備份真的有用嗎?

讓我們來驗證一下。

首先,使用你的瀏覽器,回到你的 PHPMyAdmin 工作階段(如果逾時,可能需要重新驗證),並以瀏覽模式(Browse)進入 demo 資料表。確認我們的兩筆測試資料都還在。

這時你可以隨意選擇一筆資料,刪除它。這在 PHPMyAdmin 中非常簡單——只要點選你想刪除那一列的 “Delete” 文字。系統會跳出一個 “Confirm” 確認視窗,然後顯示刪除成功的訊息,頁面會重新整理,只剩下一筆資料。

接著,回到 demo 資料庫的 “database” 頁面,可以在 PHPMyAdmin 左側邊欄點選資料庫名稱(“demo”)。主視窗會顯示我們的 “demotable”,而狀態欄位 “Rows” 會顯示只剩一筆資料。

在主視窗上方有一系列指令分頁,從 “Structure” 和 “SQL” 開始。請選擇名為 “Import” 的分頁。 “Import” 視窗的第一部分是 “File to import:”。點選文字方塊旁的 “Browse” 按鈕(預設顯示 “No file selected”),然後在你的檔案系統中找到剛剛寫入或複製的 .sql 檔案。確認檔案正確後選取它。

你不需要更改匯入的任何預設參數,只要捲動到頁面底部,點選 “Import” 按鈕即可。深呼吸、交叉手指、祝你好運。

匯入完成後,回到上方選單再次選擇 “Browse” 分頁。在畫面中央你應該會看到資料表中的兩筆資料,剛剛被你刪除的那筆資料也已經透過匯入流程安全還原。

恭喜你!

你現在已經成功——手動——完成了從 Container MariaDB Server 備份到本機檔案系統的流程。如果你日後真的需要從定期備份中進行還原(“in anger”——因為你真的需要救回資料),這就是你該使用的流程。

我們已經非常接近完成了!!!

13. 自動化備份流程

雖然這些手動步驟很有幫助,但如果每次都要親自執行會顯得有些繁瑣,因此我們可以利用 QNAP NAS 和 QTS 作業系統提供的 cron 工具來自動化這個流程。(對於非 Unix 讀者來說,“cron” 也是一個縮寫——這次來自 “chronological”,表示這是一個基於時間的控制工具。)

首先,我們將撰寫一個 Shell 腳本來自動執行備份步驟。我們會將這個腳本放在一個只有 NAS 管理員可見、但一般使用者無法存取的資料夾位置。這可以透過專用的「管理員共用」(Admin Share),或是使用 Public 共用資料夾再透過資料夾權限限制腳本資料夾的存取權限來達成。當然,我們選擇的這個位置也應該被納入 HBS3 備份範圍內……

檔案內容需包含與下列範例等效的指令——你可以依照自己的需求進行自訂:

#!/bin/bash
#

docker exec -it {YourContainerName} mariadb-dump -h 127.0.0.1 -P3306
-u {yourBackupAccountName} -p{yourBackupAccountPassword}
-databases {yourDatabaseName}
-result-file /var/backups/{yourDatabaseName}.sql

如果你已經從 MariaDB 容器建立了「橋接」資料夾到 NAS 檔案系統,則不需要以下這一行:

docker cp {YourContainerName}:var/backups/{yourDatabaseName}.sql /share/NFSv=4/Public/Backup/

這時你應該將「-result-file」參數改為 NAS「Public」共用資料夾中指定的目的地目錄。

第二條指令「docker cp」的意思是「Docker Copy」,如其名所示,就是將放在容器內部的備份自動複製到容器外部的位置,方便納入常規備份。

請特別注意「—databases」和「—result-file」的前綴是連字符(–),不是單連字符(-)……另外也要注意,這些指令在腳本中不需要加上「sudo」前綴——cron 會以 root 權限執行該腳本。

在這個範例中,我們假設上述腳本儲存於:

/share/NFSv=4/Public/Software/QNAP/scripts/DockerMariaDBbackup.sh

進入存放腳本的資料夾並執行以下指令:

ls -al

檢查腳本的權限,應該會像 -rwxrwxr-x 這樣。

實際上權限設定不用太過嚴格,只要每組三個字元中都有「x」,代表檔案擁有者、擁有者群組與其他使用者都可執行即可。

請在 NAS SSH 連線下,輸入以下指令測試腳本是否能如預期執行:

sudo /share/NFSv=4/Public/Software/QNAP/scripts/DockerMariaDBbackup.sh

請依據你實際的資料夾路徑與腳本名稱做替換。

由於我們以 root 權限執行該腳本(指令前加上「sudo」),系統會要求你輸入密碼。輸入後,腳本應該可以順利執行。請用你的工作站檔案總管前往「/Backup/」資料夾,檢查剛建立的檔案日期,確認是否成功寫入。

現在只剩下自動排程備份工作的部分。

首先,前往 QNAP 參考文件,這裡 並詳細閱讀如何編輯 crontab 的說明。從說明中可以看到,絕對不要用「crontab -e」這種「傳統」方式,而是必須手動編輯相關檔案。

接著,開啟新的瀏覽器分頁,前往 https://crontab.guru/,這是一個非常實用的工具頁面,可以幫你產生「crontab 字串」,讓你的備份工作在指定日期與時間自動執行。

當你從 guru 頁面得到排程語法後——並依照上述 QNAP 參考文件的說明——在 QNAP crontab 設定檔中加入該字串。

舉例來說……我每天凌晨 01:45 執行備份,crontab 的設定如下:

45 1 * * * /share/NFSv=4/Public/Software/QNAP/scripts/DockerMariaDBbackup.sh 2>/dev/null

也許不太明顯,但指令最後的「2>/dev/null」其實是在告訴 cron,如果腳本產生任何錯誤,這些錯誤訊息會被直接忽略。為什麼要這麼做?因為這個腳本很簡單,而且我已經徹底測試過——而且我每週至少會檢查一次備份結果。另外,關於 crontab 檔案中的這一行要注意……每次 QTS 更新時,crontab 檔案中的條目順序通常會被重新排列。我不敢說這完全是隨機的,但如果有什麼規律,我還沒搞懂。如果你之後回來檢查,發現你加的那一行不是最後一行,不用擔心——只要掃描一下清單,它一定還在裡面。

14. 給自己一個掌聲

我是認真的。不是因為你成功在 ContainerStation 中設置了 MariaDB、配置並測試了備份,然後還設置了自動備份排程。而是恭喜你有毅力把這份指南一路讀到最後!

我真的很佩服!

在你離開之前,我有兩個小小的請求。首先,如果你發現有任何可以改進、澄清、簡化或修正的地方,留下評論告訴我——或直接訊息我。

其次,如果這份指南對你有幫助,考慮「善的循環」。如果你自己也解決了什麼問題——不管是 QNAP NAS、MariaDB 還是其他東西,請到相關論壇分享你的經驗。你不只是幫助自己,也是幫助大家。

謝謝你。