Docker

一、為什麼需要 Docker?

在容器化之前,開發者常遇到 「在我電腦上可以跑」 的問題:

  • 本機 Node 版本與 CI / 正式環境不一致
  • 作業系統差異(Windows / macOS / Linux)導致原生模組編譯失敗
  • 依賴 PostgreSQL、Redis 等服務,本機安裝與設定繁瑣
  • 部署流程與開發環境脫節

Docker 將應用程式及其所有依賴(執行環境、函式庫、設定)打包成可移植的映像檔(Image),在任何支援 Docker 的機器上以一致的方式執行。

Docker 解決的核心問題

問題Docker 解法
環境不一致映像檔鎖定 OS + Node 版本
依賴管理複雜Dockerfile 宣告所有依賴
多服務協作Docker Compose 一鍵啟動
部署可重複同一映像檔 → dev / staging / prod

二、核心概念

2.1 映像檔(Image)vs 容器(Container)

概念類比說明
Image程式安裝包 / 藍圖唯讀模板,由 Dockerfile 建置
Container執行中的程式Image 的執行實例,可啟停、刪除
flowchart LR
    A["Dockerfile"] --> B["docker build"]
    B --> C["Image 🖼️"]
    C --> D["docker run"]
    D --> E["Container 📦"]

2.2 其他重要名詞

  • Registry:映像檔倉庫,最常用 Docker Hub
  • Volume:持久化資料,容器刪除後資料仍保留
  • Network:容器間通訊的虛擬網路
  • Layer:映像檔由多層堆疊,共用層可快取加速建置
  • Multi-stage Build:多階段建置,縮小最終映像檔體積

三、安裝 Docker

  • Windows
    1. 下載 Docker Desktop for Windows
    2. 啟用 WSL 2(建議)
    3. 安裝後執行 docker --version 驗證
  • macOS
    1. 下載 Docker Desktop for Mac
    2. Apple Silicon 選 ARM64 版本
    3. 執行 docker --version 驗證
  • Linux(Ubuntu 範例) curl -fsSL <https://get.docker.com> | sh sudo usermod -aG docker $USER newgrp docker docker --version

驗證安裝成功:執行 docker run hello-world,看到 “Hello from Docker!” 即代表正常。


四、指令

指令用途
docker build -t 名稱:標籤 .從 Dockerfile 建置映像檔
docker run -p 3000:3000 名稱啟動容器並映射 port
docker ps列出執行中容器
docker ps -a列出所有容器(含已停止)
docker images列出本機映像檔
docker logs 容器ID查看容器日誌
docker exec -it 容器ID sh進入容器 shell
docker stop / rm停止 / 刪除容器
docker rmi刪除映像檔
docker compose up -d背景啟動 Compose 服務

五、Dockerfile 基礎

Dockerfile 是一系列指令,描述如何建置映像檔:

# 基底映像
FROM node:20-alpine

# 工作目錄
WORKDIR /app

# 先複製 package 檔(利用 layer cache)
COPY package*.json ./
RUN npm ci

# 複製原始碼
COPY . .

# 建置(Next.js 範例)
RUN npm run build

# 對外 port
EXPOSE 3000

# 啟動命令
CMD ["npm", "start"]
Code language: PHP (php)

常用指令說明

  • FROM:基底映像(alpine 體積小,適合 production)
  • WORKDIR:設定容器內工作目錄
  • COPY / ADD:複製檔案(一般用 COPY 即可)
  • RUN:建置時執行命令
  • EXPOSE:文件化 port(實際映射靠 docker run -p
  • CMD / ENTRYPOINT:容器啟動時執行的命令

六、.dockerignore

避免把不必要檔案送進建置 context,加速建置並縮小映像檔:

node_modules
.next
.git
.env*.local
docker-compose*.yml
Dockerfile*
README.md
npm-debug.log*
Code language: CSS (css)

七、Redis

Redis 是一個記憶體資料庫,主要用來當作系統的「快取(Cache)」、透過將查詢的資料存在記憶體(RAM),降低傳統資料庫(如 MySQL)的負擔。

舉個栗子: 假如你是圖書館的櫃檯管理員,學生會一直來找你問問題:

  • 傳統資料庫(MySQL): 就像是圖書館裡的的大書庫。裡面藏書萬卷(資料量極大、結構嚴謹),但你每次要找資料,都要親自走進密密麻麻的書架裡翻找(硬碟讀寫 I/O),速度比較慢。如果突然有 1,000 個學生同時衝進來問同一個問題,大書庫就會卡到爆炸。
  • Redis: 像是你櫃檯桌面上的一張「便利貼」。把最熱門、全校學生每天都在問的問題與答案(例如:日語相關書籍在哪? 在5樓。)直接寫在便利貼上。因為就在桌面上, 0.001 秒就能直接回答,這就是記憶體讀取。

聽起來很讚,但缺點也很明顯,就是記憶體很貴,而且如果電腦突然斷電,記憶體裡的資料有可能會遺失。