Docker BuildKit Cache Mount 的隱形陷阱

症狀:部署成功,程式碼卻是舊的 一個新功能已經 commit 並推上 Git,Jenkins pipeline 顯示建置成功、部署完成,Kubernetes Pod 也順利啟動。進入 Pod 檢查——程式碼還是舊的。 這不是網路延遲、不是 image pull policy、不是 tag 衝突。問題藏在 Dockerfile 裡一行看起來「很聰明」的快取優化。 背景知識:Docker 建置的關鍵概念 在進入除錯過程之前,先釐清幾個 Docker 建置中的核心概念: Docker Image 與 Layer(映像檔與分層) Docker 映像檔由多個唯讀的「層」(layer)堆疊而成。Dockerfile 裡的每一條指令(如 COPY、RUN)都會產生一層。Docker 會對每一層計算 hash,下次建置時如果指令和輸入都沒變,就直接重用該層——這就是 layer cache。 BuildKit BuildKit 是 Docker 18.09 之後引入的新一代建置引擎(透過 DOCKER_BUILDKIT=1 啟用)。相比傳統引擎,BuildKit 支援平行建置、更聰明的快取策略,以及本文主角——--mount=type=cache(cache mount)語法。 Cache Mount(--mount=type=cache) BuildKit 專有的功能。它在 RUN 指令執行期間,將一個持久化的目錄掛載到容器內的指定路徑。這個目錄由 BuildKit 管理,不會被寫入最終的 image layer,但內容會跨越不同次的 docker build 保留下來。常見用途是快取套件管理器的下載目錄(如 yarn cache),避免每次建置都重新下載。 Inline Cache 與 --cache-from 另一種 BuildKit 快取策略。透過 --build-arg BUILDKIT_INLINE_CACHE=1 把快取 metadata 嵌入產出的 image,再用 --cache-from 從遠端 registry 拉取。這讓不同機器(例如 CI runner)也能共享建置快取。 ...

February 18, 2026 · 2 分鐘 · Peter

功能部署後憑空消失?一場 Jenkins Workspace 的除錯之旅

問題:功能「先在後不在」 我們替 Strapi 後台新增了 MFA(Multi-Factor Authentication)雙因素認證功能。第一次部署到 STG 時一切正常——登入攔截、TOTP 驗證、QR Code 設定流程都運作良好。 但幾天後,因為其他功能的修改推了新的 git tag stg-1.24,部署流程順利完成,Jenkins 顯示綠燈——打開 STG 後台,MFA 的登入流程卻完全不見了。 沒有錯誤訊息、沒有 crash log,功能就這樣無聲無息地消失。 這比「功能從未出現」更令人困惑:明明之前部署是好的,程式碼也沒有人動過 MFA 相關的部分,為什麼會突然不見? 調查過程:逐層排除 確認 Git Tag 內容 第一個直覺是——程式碼真的有被包進 tag 嗎? # 確認 tag 指向的 commit 包含 MFA 程式碼 git show stg-1.24:src/index.ts | grep -i mfa 結果確認 src/index.ts 中有 import { registerMfaRoutes } from './mfa/controller',src/mfa/ 目錄也完整存在。Git tag 本身沒問題。 檢查 Pod 內的實際檔案 既然 tag 正確,問題可能出在建置或部署階段。直接進到 Kubernetes Pod 裡看: # 進入 STG pod 檢查 kubectl exec -it deployment/strapi-stg -- sh # 檢查編譯後的檔案 ls dist/src/mfa/ # 結果:ls: dist/src/mfa/: No such file or directory # 檢查原始碼 ls src/mfa/ # 結果:ls: src/mfa/: No such file or directory MFA 相關檔案完全不存在於 Pod 中。 甚至連原始碼都沒有被複製進 Docker image。 ...

February 12, 2026 · 3 分鐘 · Peter

Vue.js SPA 社交分享完整指南:解決 Facebook/LINE OpenGraph 爬蟲問題

引言:當精美的網站變成分享時的「無名氏」 在現代 Web 開發中,社交媒體分享功能是不可或缺的一部分。當用戶在 Facebook、LINE 或其他社交平台分享你的網站連結時,你希望顯示的是精美的預覽卡片,而不是空白或錯誤的資訊。 然而,對於使用 Vue.js、React、Angular 等前端框架開發的單頁應用程式(SPA),這個看似簡單的需求卻隱藏著技術挑戰。 本文將完整記錄從問題發現、原因分析、到解決方案實作的全過程。 問題發現:為什麼分享連結總是顯示預設值? 場景描述 我的平台 www.abc.com 是一個基於 Vue.js 3 + Strapi CMS 的網站。某天,我發現一個嚴重問題: 當用戶分享服務頁面(如 https://www.abc.com/service-us/6)到 Facebook 或 LINE 時,顯示的預覽資訊總是預設值,而非該服務的實際標題和描述。 實際情況對比: 情境 期望結果 實際結果 分享服務頁面 顯示「專業網站開發服務」 顯示「ABCDEFG(預設標題)」 分享部落格文章 顯示文章標題與摘要 顯示網站預設描述 分享產品頁面 顯示產品圖片與名稱 顯示網站 Logo 診斷工具測試 使用 Facebook Open Graph Debugger 測試後發現: 爬蟲抓取到的 HTML: <!DOCTYPE html> <html lang="zh-TW"> <head> <meta charset="UTF-8"> <title>ABCDEFG</title> <meta property="og:title" content="ABCDEFG"> <meta property="og:description" content="預設網站描述"> <!-- 沒有任何動態內容! --> </head> <body> <div id="app"></div> <script src="/assets/index.js"></script> </body> </html> ⚠️ 關鍵發現: 爬蟲只看到靜態的 HTML 模板,完全沒有 JavaScript 執行後動態生成的 meta 標籤。 ...

July 31, 2025 · 11 分鐘 · Peter

從 GitLab CI 到 Kubernetes 自動化部署:完整 CI/CD Pipeline 實戰指南

引言:打破手動部署的迷思 「為什麼我的 CI 已經產出 prod-0.54,卻還得手動去跑 kubectl apply -f deployment.yaml?那不是多此一舉嗎?」 如果你也曾陷入這樣的疑問,本文將從根本理清 CI/CD 與 Kubernetes 之間的分工,並學會如何「一鍵從程式碼到雲端服務」完全自動化。 CI/CD vs. Kubernetes:各司其職的完美搭檔 在軟體開發的世界裡,GitLab CI/CD 和 Kubernetes 常常被搭在一起討論,卻扮演著截然不同的角色。 CI/CD 的職責:生產線 GitLab CI/CD 的工作內容: 建置(Build):將程式碼打包成 Docker 映像 標記(Tag):為映像貼上版本號標籤(例如 0.54、v1.0.0) 推送(Push):把 Docker 映像推到映像庫(AWS ECR、Docker Hub) Kubernetes 的職責:配送中心 Kubernetes 的工作內容: 部署(Deploy):在叢集裡建立 Pod 並執行容器 監控(Monitor):監控運行狀況,Pod 死掉自動重啟 更新(Update):滾動更新(Rolling Update)時保證服務不中斷 維運(Operate):調整副本數量、健康檢查、網路規則 分工比喻 如果把軟體交付比喻成流水線: 角色 比喻 職責 CI/CD 工廠組裝工人 把原料(程式碼)生產成成品(Docker 映像),打上編號(Tag) Kubernetes 物流配送中心 拿到成品後送到倉庫(叢集),確保正確分配、穩定運行 ⚠️ 關鍵問題: 若只把「生產出映像」交給 CI/CD,卻沒有「派送到叢集裡面運行」的步驟,流程就會中斷——就好比你生產一箱箱可口可樂,卻一直放在廠區裡沒人去配送到超商。 完整自動化流程架構 讓我們先看看完整的自動化部署流程: 流程說明: ...

June 5, 2025 · 8 分鐘 · Peter

如何使用 psql 連線 AWS RDS PostgreSQL 並在容器與 Pod 中操作

前言 在現代雲端架構中,資料庫通常部署在受保護的私有網路環境(Private Subnet)中,以提升安全性。AWS RDS(Relational Database Service)作為主流的托管資料庫服務,提供了多種連線方式,但對於初學者來說,如何在不同環境(本機、Docker、Kubernetes)中正確連線到 RDS 往往充滿挑戰。 這篇文章將深入探討: AWS RDS 網路架構:公有子網 vs 私有子網的差異 直接連線方式:當 RDS 設為 Publicly Accessible 時 SSH 隧道(SSH Tunneling):透過 Bastion Host 連線私有 RDS 容器環境連線:在 Docker 和 Kubernetes Pod 中使用 psql psql 完整命令參考:從基礎查詢到進階操作 安全最佳實踐:如何保護資料庫連線與憑證 常見問題排查:連線失敗的系統化診斷方法 無論你是在本機開發、容器化部署、或是 Kubernetes 叢集中操作,這篇文章都能幫助你建立安全可靠的資料庫連線。 AWS RDS 網路架構概覽 在開始連線之前,我們需要理解 AWS RDS 的網路架構。RDS 實例可以部署在不同的網路環境中,每種配置都有不同的連線方式和安全考量。 公有子網 vs 私有子網 兩種部署方式的比較 特性 公有子網 (Publicly Accessible) 私有子網 (Private) 直接連線 ✅ 可以從網際網路直接連線 ❌ 無法直接連線 安全性 ⚠️ 較低,暴露在公網 ✅ 高,完全隔離 連線方式 psql 直連 需要 Bastion Host / VPN 適用場景 開發測試環境 生產環境(推薦) 成本 RDS 費用 RDS + Bastion Host 費用 維護複雜度 低 中等(需管理 Bastion) 最佳實踐: ...

May 26, 2025 · 17 分鐘 · Peter