【Docker 入門系列】#04 Docker Compose 快速上手:一鍵啟動多容器環境

測驗:Docker Compose 快速上手

共 5 題,點選答案後會立即顯示結果

1. Docker Compose 主要解決什麼問題?

  • A. 讓 Docker 映像檔更小
  • B. 用一個設定檔管理多個相互連接的容器
  • C. 取代 Dockerfile 的功能
  • D. 讓容器可以在不同作業系統執行

2. 在 docker-compose.yml 中,ports: ["8080:80"] 這行設定代表什麼意思?

  • A. 容器的 8080 port 對應到主機的 80 port
  • B. 同時開放 8080 和 80 兩個 port
  • C. 主機的 8080 port 對應到容器的 80 port
  • D. 只允許從 8080 到 80 的單向連線

3. 在 Docker Compose 中,如果 Web 服務要連線到資料庫服務(服務名稱為 db),DB_HOST 應該設定為什麼?

  • A. localhost
  • B. db
  • C. 127.0.0.1
  • D. database

4. 執行 docker compose down -v 指令會發生什麼事?

  • A. 只停止容器,不移除
  • B. 停止並移除容器,保留資料
  • C. 顯示詳細的執行過程(verbose mode)
  • D. 停止並移除容器,同時刪除 volumes(資料會消失)

5. 以下哪個設定可以確保資料庫的資料在容器重啟後不會消失?

services: db: image: mysql:8 # 缺少什麼設定?
  • A. restart: always
  • B. volumes: 設定資料卷掛載
  • C. depends_on: 設定相依服務
  • D. environment: 設定環境變數

一句話說明

Docker Compose 讓你用一個設定檔就能同時啟動多個相互連接的容器。

為什麼需要 Docker Compose?

在前幾篇文章中,我們學會了用 docker run 啟動單一容器。但實際開發時,一個應用程式通常需要多個服務:

你的應用程式架構可能長這樣:
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Web App   │───▶│  Database   │    │    Redis    │
│  (Node.js)  │    │  (MySQL)    │    │   (快取)    │
└─────────────┘    └─────────────┘    └─────────────┘
Code language: CSS (css)

沒有 Docker Compose 時,你需要:

# 啟動 MySQL
docker run -d --name mysql-db -e MYSQL_ROOT_PASSWORD=secret mysql:8

# 啟動 Redis
docker run -d --name redis-cache redis:alpine

# 啟動你的 App,還要連結其他容器
docker run -d --name my-app --link mysql-db --link redis-cache my-app:latest
Code language: PHP (php)

問題來了

  • 每次都要打一堆指令
  • 指令順序很重要(資料庫要先啟動)
  • 團隊成員可能用不同的參數

Docker Compose 的解法:把所有設定寫在一個 docker-compose.yml 檔案,一個指令搞定。

最小範例

檔案結構

my-project/
└── docker-compose.yml

docker-compose.yml

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
Code language: CSS (css)

啟動

docker compose up

這段在幹嘛

  • 定義一個叫 web 的服務
  • 使用 nginx:alpine 映像檔
  • 把容器的 80 port 對應到你電腦的 8080 port

打開瀏覽器訪問 http://localhost:8080,就能看到 Nginx 預設頁面。

docker-compose.yml 基本結構

services: # 定義所有服務(容器)
  服務名稱:
    image: 映像檔 # 使用哪個映像檔
    ports: # Port 對應
      - "主機:容器"
    environment: # 環境變數
      - 變數=值
    volumes: # 資料卷掛載
      - 主機路徑:容器路徑
Code language: PHP (php)

翻譯

你會看到 意思
services: 接下來要定義有哪些容器
image: nginx 這個容器用 nginx 映像檔
ports: ["8080:80"] 外面 8080 連進來會到容器的 80
environment: 設定容器內的環境變數
volumes: 把主機的檔案/資料夾掛進容器

實戰:Web + Database 開發環境

這是最常見的情境:一個 Web 應用 + 一個資料庫。

docker-compose.yml

services:
  # 資料庫服務
  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: myapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass
    volumes:
      - db-data:/var/lib/mysql
    ports:
      - "3306:3306"

  # Web 應用服務
  web:
    image: node:18-alpine
    working_dir: /app
    volumes:
      - ./src:/app
    ports:
      - "3000:3000"
    environment:
      DB_HOST: db
      DB_USER: appuser
      DB_PASSWORD: apppass
    depends_on:
      - db
    command: npm start

volumes:
  db-data:
Code language: PHP (php)

逐段解釋

db 服務(MySQL 資料庫)

db:
  image: mysql:8 # 使用 MySQL 8 版本
  environment: # MySQL 需要的環境變數
    MYSQL_ROOT_PASSWORD: rootpass # root 密碼
    MYSQL_DATABASE: myapp # 自動建立的資料庫名稱
    MYSQL_USER: appuser # 新增的使用者
    MYSQL_PASSWORD: apppass # 使用者密碼
  volumes:
    - db-data:/var/lib/mysql # 資料保存位置(重要!)
  ports:
    - "3306:3306" # 讓你用工具連進來看資料
Code language: PHP (php)

web 服務(Node.js 應用)

web:
  image: node:18-alpine # 使用 Node.js 18
  working_dir: /app # 容器內的工作目錄
  volumes:
    - ./src:/app # 把本機 src 資料夾掛進去
  ports:
    - "3000:3000"
  environment:
    DB_HOST: db # 注意!這裡用服務名稱當主機名
    DB_USER: appuser
    DB_PASSWORD: apppass
  depends_on:
    - db # 確保 db 先啟動
  command: npm start # 容器啟動後執行的指令
Code language: PHP (php)

volumes 區塊

volumes:
  db-data: # 宣告一個命名 volume
Code language: PHP (php)

翻譯:這是告訴 Docker「幫我管理一個叫 db-data 的儲存空間」。資料庫的資料會存在這裡,即使容器刪除了,資料還在。

常用指令

啟動服務

# 前景執行(看得到 log)
docker compose up

# 背景執行
docker compose up -d

# 只啟動特定服務
docker compose up db
Code language: PHP (php)

停止服務

# 停止並移除容器
docker compose down

# 停止並移除容器 + 刪除 volume(資料會消失!)
docker compose down -v
Code language: PHP (php)

查看狀態

# 看有哪些容器在跑
docker compose ps

# 看 log
docker compose logs

# 即時看特定服務的 log
docker compose logs -f web
Code language: PHP (php)

重新建立

# 重新建立容器(設定有改的時候)
docker compose up -d --build

# 強制重新建立
docker compose up -d --force-recreate
Code language: PHP (php)

常見變化

變化 1:使用 build 而非 image

當你有自己的 Dockerfile:

services:
  web:
    build: . # 用目前目錄的 Dockerfile 建立
    ports:
      - "3000:3000"
Code language: PHP (php)

或指定 Dockerfile 位置:

services:
  web:
    build:
      context: ./app
      dockerfile: Dockerfile.dev

翻譯:不用現成映像檔,改用 Dockerfile 自己建一個。

變化 2:服務之間的網路連線

services:
  web:
    environment:
      DB_HOST: db # 直接用服務名稱當主機名!
Code language: PHP (php)

這在幹嘛:Docker Compose 會自動建立網路,讓服務之間可以用「服務名稱」互相連線。db 這個名稱會自動解析成 db 容器的 IP。

變化 3:多個 Compose 檔案

# 用開發環境設定
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

# 用正式環境設定
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Code language: CSS (css)

翻譯:可以把共用設定放 docker-compose.yml,環境特定的設定放其他檔案,啟動時合併使用。

Vibe Coder 檢查點

看到 AI 寫的 docker-compose.yml 時確認:

  • [ ] 資料有保存嗎? 資料庫服務有沒有設定 volumes?沒有的話,容器重啟資料會消失
  • [ ] Port 有衝突嗎? 檢查 ports 設定,確認本機 port 沒有被其他程式占用
  • [ ] 環境變數安全嗎? 密碼不要直接寫在檔案裡,正式環境應該用 .env 檔案
  • [ ] 啟動順序對嗎? 依賴其他服務的要加 depends_on
  • [ ] 服務名稱有意義嗎? 服務名稱會變成網路主機名,取個好認的名字

常見問題

Q: 我改了程式碼,但容器沒有更新?

A: 如果是用 volumes 掛載的程式碼,改了應該會即時生效。如果是 build 進映像檔的,需要重新 build:

docker compose up -d --build

Q: 容器啟動後馬上就停了?

A: 用 docker compose logs 服務名稱 看錯誤訊息。常見原因:

  • 設定檔格式錯誤(YAML 很在意縮排)
  • 必要的環境變數沒設定
  • Port 已被占用

Q: 資料庫連不上?

A: 檢查這幾點:

  • Web 服務的 DB_HOST 是不是用服務名稱(如 db)而不是 localhost
  • 有沒有加 depends_on(雖然這只保證啟動順序,不保證資料庫準備好了)
  • 資料庫的帳號密碼設定對不對

延伸:知道就好

這些進階功能遇到再查:

  • profiles:定義服務群組,只啟動特定群組
  • networks:自訂網路設定,隔離不同服務群組
  • healthcheck:健康檢查,確保服務真的準備好了
  • secrets:安全地管理敏感資訊
  • deploy:用於 Docker Swarm 的部署設定

總結

情境 指令
啟動所有服務 docker compose up -d
停止所有服務 docker compose down
看哪些在跑 docker compose ps
看 log docker compose logs -f
重新建立 docker compose up -d --build

記住這個工作流程

  1. 寫好 docker-compose.yml
  2. docker compose up -d 啟動
  3. 開發、測試
  4. docker compose down 收工

恭喜你完成 Docker 入門系列!現在你已經掌握了:

  • Docker 是什麼、為什麼要用
  • 如何使用 Docker 映像檔和容器
  • 如何用 Dockerfile 打包應用程式
  • 如何用 Docker Compose 管理多容器環境

這些知識足夠讓你看懂 AI 生成的 Docker 相關程式碼,也能自己動手設定開發環境了。

進階測驗:Docker Compose 快速上手

測驗目標:驗證你是否能在實際情境中應用所學。
共 5 題,包含情境題與錯誤診斷題。

1. 你正在開發一個 Node.js 專案,需要連接 MySQL 資料庫。你想要在本機開發時,程式碼修改後能即時生效,而且資料庫資料要保留。應該怎麼設定 docker-compose.yml? 情境題

  • A. 只設定 depends_on 確保啟動順序正確
  • B. 用 build 把程式碼打包進映像檔
  • C. Web 服務用 volumes 掛載程式碼,DB 服務用命名卷保存資料
  • D. 設定 restart: always 讓容器自動重啟

2. 小明執行 docker compose up 後,Web 應用無法連接到資料庫。以下是他的設定檔,問題在哪? 錯誤診斷

services: db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: secret web: image: node:18 environment: DB_HOST: localhost DB_PASSWORD: secret
  • A. 缺少 ports 設定
  • B. DB_HOST 應該設成服務名稱 db,而不是 localhost
  • C. 缺少 depends_on 設定
  • D. MySQL 映像檔版本太舊

3. 你修改了 Dockerfile 並更新了一些設定,執行 docker compose up -d 後發現變更沒有生效。你應該執行什麼指令? 情境題

  • A. docker compose restart
  • B. docker compose down && docker compose up -d
  • C. docker compose logs
  • D. docker compose up -d –build

4. 小美執行 docker compose down -v 後,重新啟動服務發現資料庫是空的。這是什麼原因? 錯誤診斷

  • A. MySQL 映像檔損壞了
  • B. 環境變數設定錯誤
  • C. -v 參數會刪除 volumes,資料庫的資料儲存在 volume 中所以被刪除了
  • D. 需要先執行 docker compose pull 更新映像檔

5. 團隊想要在開發環境和正式環境使用不同的設定(例如開發時開放更多 port),應該怎麼做? 情境題

  • A. 維護兩份完全獨立的 docker-compose.yml
  • B. 用多個 Compose 檔案,啟動時合併:docker compose -f docker-compose.yml -f docker-compose.dev.yml up
  • C. 在 docker-compose.yml 中用 if-else 判斷環境
  • D. 每次手動修改設定後再執行

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *