iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0

Day19_用 Docker 建立我們要的資料庫環境

前言

上一篇談 Git 時,我們把程式與文件的修改保存成一個個版本。真正開始開發 ProjectManagementWeb 前,還有一件事要準備:讓程式有一套 SQL Server 可以連線。

我的主要開發環境是 macOS。若每位協作者都自己安裝 SQL Server、設定 Port,再憑印象調整選項,每台電腦最後可能長得不太一樣。程式連不上資料庫時,也會很難判斷究竟是 Code 有問題,還是哪一台電腦少做了一個設定。

這次把資料庫交給 Docker。需要的 SQL Server 版本系列、Port 和資料要存在哪裡,都寫進 compose.yaml。之後不論是自己重建環境,還是請另一位開發者加入專案,都能從同一份設定開始。

在下指令前,先認識幾個等一下會遇到的名詞:

名詞 可以先把它想成 在本文負責的事情
Image 建立環境的唯讀範本 提供 SQL Server 與執行所需的檔案
Container 依照範本開出來、正在運作的房間 實際執行 SQL Server
Volume 放在房間外的置物櫃 保存資料庫檔案
Compose 環境配置清單 記錄 Image、Port、密碼來源與 Volume

同一份 Image 可以建立多個 Container,就像同一張房間設計圖可以蓋出多個房間。Container 也不是完整的虛擬機器;它會共用 Docker Host 的作業系統核心,因此通常比虛擬機器輕量。在 macOS 的 Docker Desktop 中,這個 Host 實際上是 Docker 背後的 Linux 虛擬機器,不是 macOS 核心。這裡的 Container 指 Docker Container,和 Day5 的 C4 Container 不是同一個概念。

安裝 Docker

Windows 與 macOS 可以安裝 Docker Desktop。它已經包含 Docker Engine、Docker CLI 與 Docker Compose。安裝完成後要先啟動 Docker Desktop,再開啟終端機執行:

docker version
docker compose version

docker version 正常時,會同時看到 Client 與 Server 資訊。Client 像操作櫃台,Server 才是真正建立 Container 的工作人員。如果畫面只有 Client,或出現無法連線到 Docker daemon 的訊息,通常是 Docker Desktop 還沒啟動,不是指令少打一個字。

這裡還有一項硬體限制要先說清楚。Microsoft 官方只支援在 Intel/AMD x86-64 Linux Host 上執行 SQL Server Linux Container。Apple Silicon Mac 可以在 Compose 裡加入 platform: linux/amd64,讓 Docker Desktop 嘗試用模擬方式執行,但 Rosetta 2、QEMU 等模擬環境不在 Microsoft 的測試與支援範圍內。

因此,下面的設定適合拿來做本機練習與開發。如果 Apple Silicon 上無法啟動,不能直接推論是 SQL Server 或 Compose 設定寫錯;正式環境也不應把這套模擬方式當成支援保證。

用 Compose 描述 SQL Server 環境

在專案目錄建立 compose.yaml

services:
  mssql:
    image: mcr.microsoft.com/mssql/server:2022-latest
    platform: linux/amd64
    container_name: projectmanagementweb-mssql
    environment:
      ACCEPT_EULA: "Y"
      MSSQL_PID: "Developer"
      MSSQL_SA_PASSWORD: "${MSSQL_SA_PASSWORD:?請先在 .env 設定 MSSQL_SA_PASSWORD}"
    ports:
      - "1433:1433"
    volumes:
      - mssql-data:/var/opt/mssql
    healthcheck:
      test:
        - CMD-SHELL
        - /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -C -Q "SELECT 1" -b -o /dev/null || exit 1
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
    restart: unless-stopped

volumes:
  mssql-data:

第一次看到這份檔案可能會覺得選項很多,其實它只是在回答幾個問題:

  • image:要用哪一份 SQL Server 範本。2022-latest 會跟著 SQL Server 2022 的更新移動;若團隊需要每次都取得完全相同的版本,應改用明確的 Image tag 或 digest。
  • platform:Apple Silicon 上要求以 linux/amd64 執行。若團隊全部使用 x86-64 Linux,可以移除這一行。
  • environment:接受授權條款、選擇 Developer Edition,並從外部取得 sa 密碼。
  • ports1433:1433 左邊是電腦對外開放的 Port,右邊是 SQL Server 在 Container 裡監聽的 Port。可以把它想成大樓地址與房間門牌的轉接。
  • volumes:把 Container 內的 /var/opt/mssql 接到 Docker 管理的 mssql-data。Container 拆掉後,置物櫃還在,資料不會跟著房間一起消失。
  • healthcheck:每 10 秒執行一次 SELECT 1。Container 處於 Running,只代表裡面的程式已經啟動;健康檢查通過,才表示 SQL Server 已經能回答查詢。

Volume 能讓資料跨越 Container 的生命週期,但它不是備份。電腦磁碟損壞、Volume 被刪除,資料仍然可能消失。正式環境還要另外設計資料庫備份與還原流程。

把密碼留在版本控制之外

密碼不要直接寫進 compose.yaml,也不要提交到 Git。在 compose.yaml 的同一個目錄建立 .env,並使用密碼管理工具產生符合 SQL Server 規則的密碼:

MSSQL_SA_PASSWORD=請換成自己的本機強密碼

接著確認 .gitignore 至少包含:

.env

.gitignore 只會阻止尚未被追蹤的檔案加入 Git。如果 .env 曾經進入 commit,後來才補上 .gitignore 並不會把秘密從歷史紀錄中清掉;這時應立即更換密碼,再處理 Git 紀錄。

啟動前,可以先讓 Compose 展開設定並檢查格式:

docker compose config

這個指令會把環境變數代入後顯示結果,因此畫面可能含有本機密碼。不要把完整輸出貼到 Issue、文章或公開聊天室。

下載 Image 並啟動資料庫

準備完成後,依序執行:

docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f mssql

pull 下載 Image,up -d 在背景建立並啟動 Container,ps 查看目前狀態。最後一行會持續追蹤 Log;按下 Ctrl+C 只會停止觀看,不會關閉 SQL Server。

看到下面這段訊息,表示 SQL Server 已經準備接受連線:

SQL Server is now ready for client connections

也可以再次執行 docker compose ps。健康檢查完成後,狀態應由 health: starting 變成 healthy

如果 Container 很快變成 Exited 或一直無法通過健康檢查,先查看:

docker compose logs mssql

常見原因包括密碼不符合 SQL Server 規則、電腦的 Port 1433 已被其他程式占用,或 Apple Silicon 的模擬環境無法執行這份 Image。先讀 Log,再決定要改哪裡,比反覆刪掉重建更容易找到原因。

建立 ProjectManagement 資料庫

SQL Server 啟動後,使用 Container 內附的 sqlcmd 連線:

docker compose exec mssql \
  /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -C

這裡刻意不加 -P。工具會在終端機要求輸入密碼,避免密碼直接留在 Shell 歷史紀錄中。

連線成功後,輸入:

IF DB_ID(N'ProjectManagement') IS NULL
    CREATE DATABASE [ProjectManagement];
GO

接著查詢資料庫是否存在:

SELECT name
FROM sys.databases
WHERE name = N'ProjectManagement';
GO

查詢結果出現 ProjectManagement,才算完成這一步。輸入 QUIT 可以離開 sqlcmd

ASP.NET Core 在本機可以使用以下連線字串:

Server=localhost,1433;Database=ProjectManagement;User Id=sa;Password=YOUR_PASSWORD;Encrypt=True;TrustServerCertificate=True

真正的密碼應放在 .NET User Secrets 或環境變數,不要寫進 Repository。TrustServerCertificate=True 適合這個使用本機憑證的開發環境;正式環境應使用可驗證的伺服器憑證,不要照抄這個設定。

sa 像整棟大樓的總管理員,適合用來完成本機初始化,卻不適合讓應用程式長期持有。正式設計應另建權限較小的 Login,讓 ProjectManagementWeb 只取得實際需要的資料庫權限。

這次為什麼不建立 Dockerfile?

Dockerfile 用來描述「如何建置自己的 Image」。這次直接使用 Microsoft 發布的 SQL Server Image,沒有要把 ProjectManagementWeb 或額外套件裝進去,所以在 Compose 指定 Image 就夠了。

如果另外建立一份只有下面一行的 Dockerfile:

FROM mcr.microsoft.com/mssql/server:2022-latest

最後得到的內容和原本 Image 幾乎相同,卻多了一份要維護的檔案。等到真的需要加入額外套件或自訂啟動流程,再建立 Dockerfile 會比較合理。

資料庫 Schema 也不應藏在某個人手動調整過的 Container 裡。未來會把 EF Core Migration 放在專案中,交給版本控制保存。Container 可以重建,資料表結構仍能依照 Migration 再次產生;這才符合上一篇所說的「Git 保存如何重建環境,Docker 把環境實際跑起來」。

停止與清除環境

平常停止服務可以執行:

docker compose down

這會移除 Container 與 Compose 建立的 Network,但保留命名 Volume。下次執行 docker compose up -d,SQL Server 仍會接回原本的資料。

只有確定連資料都不要了,才執行:

docker compose down -v

最後的 -v 會刪除 Volume,ProjectManagement 資料庫也會一起消失。它很適合重做本機練習環境,但執行前要先確認沒有需要保留的資料。

小結

到這裡,我們已經用一份 compose.yaml 記錄 SQL Server 的 Image、Port、密碼來源、健康檢查與資料保存方式。其他開發者拿到同一份設定後,不必各自猜安裝步驟,就能建立接近一致的本機資料庫環境。

環境準備好,還不代表應該立刻把整套需求交給 Agent 實作。Day20 會先介紹 Codex 的規劃模式,讓它讀懂現有規格、找出會受影響的檔案,再由人確認實作方向。

參考資料


上一篇
Day18_Git 是一個好工具
系列文
Codex的規格驅動開發 :30 天打造 .NET 內部專案管理系統20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言