開發者必學 Docker:映像檔、容器與 Compose
你大概聽過 Docker,也知道它能簡化開發流程。但如果你剛接觸容器,那些術語和指令可能會讓你一頭霧水。這份指南跳過冗長的理論,直接帶你實際了解 Docker 映像檔、容器與 Compose,讓你今天就能有效運用它們。
Docker 是什麼?為什麼你該在乎?
Docker 是一個平台,能將你的應用程式及其相依項目打包成一個標準化單位,稱為容器(container)。容器輕量、可攜,而且彼此隔離,這表示你可以讓應用程式在筆電、同事的電腦或正式伺服器上,以一致的方式運行。
關鍵好處是什麼?「在我電腦上可以跑啊」這種情況將成為過去式。Docker 確保你的程式碼在任何地方運行的環境都完全相同。
映像檔 vs. 容器:建構基礎
開始之前,你需要先了解映像檔(image)與容器(container)的差別。
- 映像檔:一個唯讀範本,包含你的應用程式碼、執行環境、函式庫和相依項目。可以把它想成一份快照或藍圖。
- 容器:映像檔的可執行實例。你可以啟動、停止、移動和刪除容器。同一個映像檔可以同時運行多個容器。
簡單來說:映像檔是食譜,容器則是照著食譜煮出來的菜。
開發者必備的 Docker 指令
以下是你最常用到的指令:
docker pull <image>– 從 Docker Hub 等登錄檔下載映像檔。docker images– 列出所有本機映像檔。docker run <image>– 從映像檔建立並啟動容器。docker ps– 列出執行中的容器。加上-a可查看所有容器,包括已停止的。docker stop <container>– 優雅地停止執行中的容器。docker rm <container>– 移除已停止的容器。docker rmi <image>– 移除映像檔。docker exec -it <container> bash– 在執行中的容器內開啟互動式 shell。
舉例來說,要執行一個簡單的 Nginx 網頁伺服器:
docker run -d -p 8080:80 nginx
這會拉取 nginx 映像檔(如果本機沒有),以分離模式(-d)啟動容器,並將主機的 8080 埠對應到容器內的 80 埠(-p 8080:80)。
用 Dockerfile 建構自己的映像檔
要打包你的應用程式,你需要建立一個 Dockerfile——一個包含指令的文字檔。以下是 Node.js 應用程式的簡單範例:
# Use an official Node.js runtime as a parent image
FROM node:18-alpine
# Set the working directory
WORKDIR /usr/src/app
# Copy package.json and install dependencies
COPY package*.json ./
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", "app.js"]
用以下指令建構映像檔:
docker build -t my-node-app .
然後執行它:
docker run -p 3000:3000 my-node-app
用 Docker Compose 簡化多容器應用程式
真實世界的應用程式通常需要多個服務:網頁伺服器、資料庫、快取等等。用 docker run 逐一管理會變得非常繁瑣。Docker Compose 讓你用一個 YAML 檔案定義並執行多容器應用程式。
建立一個 docker-compose.yml 檔案:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: example
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
然後用以下指令啟動所有服務:
docker compose up -d
Compose 會自動處理網路、磁碟區和相依性。要停止並移除容器、網路和磁碟區,請執行 docker compose down。
開發環境的 Docker 最佳實踐
- 使用 .dockerignore:從建構上下文中排除不必要的檔案(例如
node_modules),以加速建構。 - 善用多階段建構:將建構時期的相依項目與執行時期分開,讓最終映像檔保持精簡。
- 鎖定版本:指定確切的映像檔標籤(例如
node:18.16.0-alpine)以確保可重現性。 - 以非 root 身分執行:在 Dockerfile 中建立使用者,並用
USER切換過去,以提升安全性。 - 使用磁碟區保存資料:資料庫和其他有狀態的服務應將資料存放在磁碟區,而非容器內部。
常見陷阱與避免方法
- 映像檔過於臃腫:從最小的基礎映像檔(如 Alpine)開始,並清理套件快取。
- 連接埠衝突:確保主機連接埠未被占用。使用
docker ps檢查。 - 忽略日誌:使用
docker logs <container>來除錯。 - 本機開發未使用 Compose:即使是簡單的應用程式,也能從 Compose 的宣告式設定中受益。
常見問題
Docker 映像檔和容器有什麼不同?
映像檔是唯讀範本,定義應用程式及其環境。容器則是該映像檔的執行實例。你可以從單一映像檔建立多個容器。
單一容器的應用程式也需要 Docker Compose 嗎?
不一定。對於簡單的應用程式,docker run 就足夠了。不過,Compose 讓管理環境變數、磁碟區和網路變得更簡單,即使只有一個服務也一樣,而且日後要擴展也更方便。
如何在 Docker 中保存資料?
使用磁碟區。磁碟區儲存在容器的檔案系統之外,即使容器被刪除,資料依然存在。在 Compose 中,定義一個磁碟區並掛載到容器內的路徑(例如 volumes: - mydata:/var/lib/data)。
準備好最佳化你的 Docker 工作流程了嗎?當你需要分析容器日誌時,試試我們的 Nginx 日誌分析器,快速解析並視覺化日誌資料——非常適合除錯容器化的網頁伺服器。