開發者 Docker 指南:映像、容器與 Compose
你打造了一個在你機器上完美運行的網頁應用程式,但當你將它部署到伺服器或與隊友分享時,它卻壞了。相依套件遺失、版本衝突,或環境變數設定錯誤。這就是經典的「在我的機器上可以跑」問題。Docker 透過將你的應用程式及其相依套件打包成一個標準化單元——稱為容器——來解決這個問題。在本指南中,你將學習 Docker 的核心概念——映像、容器與 Compose——以及如何運用它們來簡化你的開發工作流程。
什麼是 Docker?
Docker 是一個用於在容器中建置、執行及交付應用程式的平台。容器是一個輕量、獨立、可執行的套件,包含執行一段軟體所需的一切:程式碼、執行環境、系統工具、函式庫及設定。容器將應用程式彼此隔離,也與底層基礎架構隔離,確保跨環境的一致性。
映像 vs. 容器
映像(image)是一個唯讀範本,內含建立容器的指令。它就像你的應用程式及其環境的快照。容器(container)則是映像的可執行實例。你可以使用 Docker API 或 CLI 來建立、啟動、停止、移動或刪除容器。
把映像想成一個類別(class),而容器則是該類別的物件(實例)。你可以從同一個映像執行多個容器,每個容器彼此隔離。
使用 Dockerfile 建置映像
Dockerfile 是一個內含建置映像指令的文字檔。以下是一個 Node.js 應用程式的簡單範例:
# Use an official Node.js runtime as a parent image
FROM node:18-alpine
# Set the working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the port the app runs on
EXPOSE 3000
# Define the command to run the app
CMD ["node", "server.js"]
要建置映像,請執行:
docker build -t my-node-app .
-t 旗標會為映像加上名稱標籤(my-node-app)。結尾的 . 則指定建置上下文(目前目錄)。
執行容器
有了映像之後,你就可以執行容器:
docker run -p 3000:3000 -d my-node-app
這會將你主機上的連接埠 3000 對應到容器內的連接埠 3000,並以分離模式(-d)執行它。
常見指令:
docker ps– 列出執行中的容器docker ps -a– 列出所有容器(包括已停止的)docker stop <container_id>– 停止容器docker rm <container_id>– 移除容器docker images– 列出映像docker rmi <image_id>– 移除映像
使用 Volume 管理資料
容器是短暫的;當它們被移除時,其資料也會遺失。若要保存資料,請使用 volume。Volume 是容器檔案系統之外的目錄,由 Docker 管理。
docker run -v my_volume:/app/data my-node-app
你也可以掛載主機目錄(bind mount)以利開發:
docker run -v $(pwd):/app my-node-app
Docker Compose:多容器應用程式
真實世界的應用程式通常需要多個服務:網頁伺服器、資料庫、快取等。Docker Compose 讓你使用 YAML 檔定義並執行多容器 Docker 應用程式。以下是一個搭配 PostgreSQL 資料庫的 Node.js 應用程式範例 docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydb
depends_on:
- db
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
使用以下指令執行整個堆疊:
docker compose up -d
這會建置 web 服務、拉取 Postgres 映像、建立網路,並啟動兩個容器。depends_on 確保資料庫在 web 服務之前啟動。
要停止並移除容器、網路及 volume:
docker compose down -v
開發環境中 Docker 的最佳實務
- 使用 .dockerignore 將
node_modules和.git等檔案排除在建置上下文之外。 - 善用多階段建置(multi-stage builds) 讓映像保持精簡。例如,在一個階段建置你的應用程式,然後只將正式環境的產物複製到較小的執行環境映像中。
- 固定版本 在你的 Dockerfile 中(例如使用
node:18-alpine而非node:latest)以確保可重現性。 - 使用 volume 保存持久性資料,並在開發期間使用 bind mount 進行程式碼即時重載。
- 讓容器保持無狀態;將狀態儲存在 volume 或外部服務中。
比較:Docker vs. 虛擬機器
| 面向 | Docker 容器 | 虛擬機器 |
|---|---|---|
| 啟動時間 | 數秒 | 數分鐘 |
| 資源使用 | 輕量(共用作業系統核心) | 笨重(每個 VM 都有完整作業系統) |
| 隔離性 | 行程層級 | 硬體層級 |
| 可攜性 | 高(任何能執行 Docker 的地方都能跑) | 受 hypervisor 相容性限制 |
常見問題
映像與容器有何不同?
映像是一個唯讀範本,定義應用程式及其環境。容器則是映像的執行中實例。你可以從同一個映像建立多個容器。
我何時應該使用 Docker Compose?
當你的應用程式由多個需要協同運作的服務組成時(例如網頁伺服器、資料庫、快取),就適合使用 Docker Compose。它能簡化開發與測試時的協調工作。
我該如何在 Docker 中保存資料?
使用 volume 將資料保存在容器的檔案系統之外。Volume 由 Docker 管理,且可在容器之間共享。也可以使用 bind mount 來掛載主機目錄。
準備好將你的下一個專案容器化了嗎?先為一個簡單的應用程式撰寫 Dockerfile,然後逐步透過 Docker Compose 新增服務。想找更多開發者工具,歡迎試試我們的 JSON Formatter 來驗證並美化你的設定檔。