本文說明 Docker 是什麼、為何使用,以及如何在本專案(Spring Boot + PostgreSQL + Gradle)中 建置映像、執行容器,並逐項解釋相關指令與檔案。專案根目錄已提供:
| 檔案 | 用途 |
|---|---|
Dockerfile |
多階段建置:編譯 JAR → 輕量 JRE 映像 |
docker-compose.yml |
同時啟動 PostgreSQL 與應用程式 |
.dockerignore |
建置脈絡排除不必要檔案,加速建置 |
1. Docker 是什麼?
Docker 是一套 容器化(containerization) 平台。它把應用程式及其依賴(執行環境、函式庫、設定方式)打包成 映像(image),再從映像啟動 容器(container)。
1.1 映像(Image)
- 唯讀的「範本」,類似 虛擬機範本,但更輕量。
- 由 層(layer) 堆疊而成;相同層可被多個映像共用,節省空間。
- 常見來源:自己用
Dockerfile建置,或從 Docker Hub 拉取官方映像(例如postgres、eclipse-temurin)。
1.2 容器(Container)
- 映像 執行後 的實例,有獨立的檔案系統視圖、網路、程序空間。
- 與 虛擬機 不同:容器共用宿主機的 Linux 核心(在 macOS/Windows 上由 Docker Desktop 提供 Linux VM),啟動快、資源開銷小。
1.3 Dockerfile
- 文字腳本,描述「如何從基底映像一步步建立出自訂映像」。
- 每一行指令通常產生一個 新層;指令順序影響 建置快取(不變的前段可重用)。
1.4 Docker Compose
- 用 YAML 定義 多個服務(例如:資料庫 + Web 應用),一鍵啟停、設定網路與依賴順序。
- 本專案的
docker-compose.yml會啟動 PostgreSQL 與 Baasid 應用,並讓應用透過 服務名稱postgres連線資料庫。
1.5 為什麼要用 Docker 包裝本專案?
- 環境一致:開發、CI、正式機都用同一套映像,減少「我機器可以跑」問題。
- 依賴清楚:Java 21、JRE、JAR 都包在映像或 Compose 裡。
- 資料庫一鍵起:Compose 內含 PostgreSQL,並掛載
sql/init.sql做首次初始化。
2. 專案內 Docker 相關檔案說明
2.1 Dockerfile(多階段建置)
本專案採 多階段建置(multi-stage build):
- 第一階段(
build):使用 JDK 21(eclipse-temurin:21-jdk-jammy),執行./gradlew bootJar產生可執行 JAR。 - 第二階段(最終映像):只保留 JRE 21(
eclipse-temurin:21-jre-jammy)與編譯好的 JAR,體積較小、攻擊面較小。
重點指令對照:
| Dockerfile 指令 | 說明 |
|---|---|
FROM ... AS build |
命名此建置階段為 build,後續可 COPY --from=build。 |
WORKDIR /app |
之後 RUN、COPY 的預設目錄設為 /app。 |
COPY gradlew ... |
將 Gradle Wrapper 與專案原始碼複製進映像(需與本機 gradlew 一致)。 |
RUN chmod +x gradlew && ./gradlew bootJar ... |
赋予執行權並建置;-x test 略過測試以縮短映像建置時間(可依需求移除)。 |
FROM eclipse-temurin:21-jre-jammy |
新的最終階段,不含 JDK 編譯器。 |
COPY --from=build /app/build/libs/*.jar app.jar |
只從建置階段取出 JAR,檔名在 Gradle 依 build.gradle 的 version 可能為 baasid-1.0.0.jar,用萬用字元避免寫死。 |
EXPOSE 8080 |
文件用途,宣告容器內應用監聽 8080;不會自動對外開埠,對外對映在 docker run -p 或 Compose ports 設定。 |
ENTRYPOINT ["java", "-jar", "/app/app.jar"] |
容器啟動時執行的固定命令;Spring Boot 可執行 JAR 內含主類別與依賴。 |
2.2 docker-compose.yml
| 區塊 | 說明 |
|---|---|
services.postgres |
使用官方 postgres:16-alpine;環境變數建立資料庫 baasid、帳密與本機 application.yml 預設一致。 |
volumes: ./sql/init.sql -> /docker-entrypoint-initdb.d/ |
PostgreSQL 映像會在 資料目錄空白時 自動執行此目錄下的 .sql,建立表與種子資料。 |
healthcheck |
用 pg_isready 確認資料庫可接受連線,避免應用在 DB 未就緒時啟動失敗。 |
services.app |
build: . 表示用目前目錄的 Dockerfile 建置映像。 |
environment.SPRING_DATASOURCE_URL |
覆寫 Spring Boot 的 spring.datasource.url;主機名必須是 postgres(Compose 內建 DNS 服務名),不可寫 localhost(在容器內 localhost 是容器自己)。 |
depends_on.condition: service_healthy |
等 PostgreSQL 健康檢查通過後才啟動 app(需 Compose v2 與支援 condition 的版本)。 |
2.3 .dockerignore
- 類似
.gitignore,不要把build/、.gradle/、.git/等複製進建置脈絡,可減少傳輸量並避免覆蓋映像內編譯結果。
3. 前置需求
- 已安裝 Docker Engine 與 Docker Compose(Docker Desktop 通常兩者皆含)。
- 在專案根目錄(與
Dockerfile、docker-compose.yml同層)執行下列指令。
終端機中可確認版本:
docker version
docker compose version
指令說明:
| 指令 | 說明 |
|---|---|
docker version |
顯示 Client/Server API 版本;確認 Docker 守護行程(daemon)有在運行。 |
docker compose version |
顯示 Compose 外掛版本(Compose V2 語法為 docker compose,舊版獨立程式為 docker-compose)。 |
若你的環境仍使用舊指令,請將本文的 docker compose 改成 docker-compose(連字號)。
4. 方式一:Docker Compose(建議)
一次啟動 PostgreSQL + Baasid,並自動初始化資料庫腳本。
4.1 建置並以背景執行
docker compose up --build -d
各參數說明:
| 參數 | 說明 |
|---|---|
docker compose |
讀取目前目錄的 docker-compose.yml,管理其中定義的服務。 |
up |
建立網路、建立並啟動容器;映像不存在則先建置。 |
--build |
啟動前先 重新建置 映像(程式碼變更後建議加上,確保 JAR 為最新)。 |
-d |
detached,在背景執行,終端機不會卡住顯示 log。 |
4.2 查看執行狀態與日誌
docker compose ps
docker compose logs -f app
| 指令 | 說明 |
|---|---|
docker compose ps |
列出 Compose 專案中各容器的狀態、埠對映。 |
docker compose logs -f app |
持續追蹤名為 app 的服務日誌;按 Ctrl+C 停止追蹤(不會停止容器)。 |
4.3 停止並移除容器
docker compose down
| 指令 | 說明 |
|---|---|
docker compose down |
停止並刪除 Compose 建立的容器與預設網路;不會刪除映像。 |
若要連匿名 volume 一併刪除(會清掉資料庫檔案,慎用):
docker compose down -v
-v:移除 Compose 宣告的 volumes。
4.4 驗證 API
應用對外為 宿主機 8080(見 ports: "8080:8080"):
- Swagger UI:
http://localhost:8080/swagger-ui.html - 登入:
POST http://localhost:8080/auth/login
5. 方式二:僅建置與執行單一應用映像
若 自行在外部提供 PostgreSQL(本機或雲端),可只建置 app 映像。
5.1 建置映像
docker build -t baasid:1.0.0 .
| 參數 | 說明 |
|---|---|
docker build |
依目前目錄的 Dockerfile 建置映像。 |
-t baasid:1.0.0 |
tag:映像名稱 baasid,標籤 1.0.0(可自訂,例如 latest)。 |
. |
建置脈絡(context):把目前目錄(遵守 .dockerignore)送給 Docker daemon。 |
5.2 執行容器(連到宿主機的 PostgreSQL)
假設 PostgreSQL 跑在宿主機的 5432,在 Linux 上可使用:
docker run --rm -p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/baasid \
-e SPRING_DATASOURCE_USERNAME=postgres \
-e SPRING_DATASOURCE_PASSWORD=postgres \
baasid:1.0.0
| 參數 | 說明 |
|---|---|
docker run |
從映像建立並啟動一個新容器。 |
--rm |
容器結束後 自動刪除 容器,適合測試。 |
-p 8080:8080 |
埠對映:宿主埠:容器埠;左側可改成例如 18080:8080。 |
-e KEY=value |
設定 環境變數,Spring Boot 會對應到 application.yml(例如 SPRING_DATASOURCE_URL → spring.datasource.url)。 |
host.docker.internal |
Docker Desktop(Mac/Windows)提供的特殊主機名,指向宿主機;Linux 上可能需加 --add-host=host.docker.internal:host-gateway 或改用實際 IP。 |
5.3 查看映像與容器
docker images
docker ps -a
| 指令 | 說明 |
|---|---|
docker images |
列出本機映像、大小、標籤。 |
docker ps |
列出 執行中 的容器。 |
docker ps -a |
列出 全部 容器(含已停止)。 |
6. Spring Boot 與環境變數對照
Compose 與 docker run -e 常用變數:
| 環境變數 | 對應設定 | 說明 |
|---|---|---|
SPRING_DATASOURCE_URL |
spring.datasource.url |
JDBC URL;Compose 內請用主機名 postgres。 |
SPRING_DATASOURCE_USERNAME |
spring.datasource.username |
資料庫使用者。 |
SPRING_DATASOURCE_PASSWORD |
spring.datasource.password |
資料庫密碼。 |
JWT_SECRET |
jwt.secret |
自訂屬性;正式環境請改為強隨機字串,勿使用範例預設值。 |
SPRING_PROFILES_ACTIVE |
spring.profiles.active |
例如 dev 會載入 application-dev.yml(含 ddl-auto: update 等)。 |
注意: 預設 application.yml 使用 spring.jpa.hibernate.ddl-auto: validate,資料表須已存在(sql/init.sql 或手動建立)。若僅本地實驗,可透過 profile 調整(需自行評估風險)。
7. 疑難排解
| 現象 | 可能原因 | 處理方向 |
|---|---|---|
| 應用啟動失敗:無法連線 DB | 資料庫尚未 healthy 或 URL 錯誤 | 確認 SPRING_DATASOURCE_URL 主機名在 Compose 網路內為 postgres;查看 docker compose logs postgres。 |
validate 與 schema 不符 |
表結構與 Entity 不一致 | 對照 sql/init.sql 與 JPA Entity,或調整設定(僅限開發環境)。 |
| 建置很慢 | 未使用快取、網路下載依賴 | 確認 .dockerignore 已排除 build/;重複建置時前段層可命中快取。 |
| 埠已被占用 | 本機 8080 或 5432 已被使用 | 修改 docker-compose.yml 的 ports 左側,例如 "8081:8080"。 |
8. 指令速查表
| 指令 | 用途 |
|---|---|
docker compose up --build -d |
建置並背景啟動 Compose 全部服務 |
docker compose down |
停止並移除 Compose 容器與預設網路 |
docker compose logs -f <服務名> |
追蹤指定服務日誌 |
docker build -t <名>:<標籤> . |
建置單一映像 |
docker run --rm -p 8080:8080 -e ... <映像> |
以前台執行單一容器(可搭配 -d 背景) |
docker images / docker ps -a |
檢視映像與容器 |
9. 安全與正式環境提醒
- 不要在映像或公開儲存庫 放入正式資料庫密碼、JWT 密鑰;應使用 環境變數、Docker secrets 或雲端密鑰管理。
- 本文件範例之帳密僅供本機/開發使用。
- 正式環境請啟用 HTTPS、限制資料庫曝露埠、定期更新基底映像(
eclipse-temurin、postgres)。
以上說明對應專案根目錄的 Dockerfile、docker-compose.yml 與 .dockerignore。若升級 Spring Boot 或變更 server.port,請同步調整 EXPOSE 與 Compose ports。