Docker 容器化部署入門教學:後端工程師必學的環境打包術
Docker 是什麼?為什麼你該學它
「在我電腦上明明可以跑啊!」——這大概是後端工程師最經典的一句話了。每次部署到正式環境,總會遇到各種環境不一致的鬼問題:Node.js 版本不對、少裝了某個系統套件、設定檔路徑不同……搞到最後比寫程式還累。
Docker 就是來解決這個問題的。簡單來說,Docker 是一套容器化技術,它能把你的應用程式連同所有依賴(runtime、套件、設定檔)打包成一個標準化的「容器」。不管這個容器跑在你的 Mac、同事的 Windows、還是 AWS 的 Linux 主機上,行為都完全一致。
你可能會問:「那跟虛擬機(VM)有什麼不同?」差別很大。VM 會模擬整個作業系統,啟動慢、佔空間大(動不動就好幾 GB)。Docker 容器共享主機的 OS 核心,啟動只要幾秒,映像檔通常幾十到幾百 MB。效率差了好幾個量級。
說白了,Docker 讓「環境即程式碼」成為可能,這也是現代 DevOps 的基石。如果你是後端工程師,不學 Docker 真的說不過去。
安裝 Docker Desktop
Docker 的安裝現在已經非常簡單了。不管你用 macOS、Windows 還是 Linux,官方都提供了 Docker Desktop 這個圖形化工具。
安裝步驟:
- 前往 Docker 官網(docker.com)下載對應作業系統的安裝檔
- macOS / Windows:執行安裝程式,一路下一步即可。Windows 用戶需要先啟用 WSL 2(Windows Subsystem for Linux)
- Linux:用套件管理器安裝,例如 Ubuntu 上執行
sudo apt-get install docker-ce docker-ce-cli containerd.io - 安裝完成後,在終端機輸入
docker --version確認安裝成功
Docker Desktop 內建了 Docker Engine、Docker CLI、Docker Compose,還有一個蠻好用的 GUI 可以管理容器和映像檔。個人建議新手先從 CLI 學起,GUI 當輔助就好——因為正式環境上你只有 CLI 可以用。
核心概念:Image、Container、Dockerfile、Registry
學 Docker 之前,有四個核心概念一定要搞清楚,不然後面會很混亂:
- Image(映像檔):可以想成是一個「唯讀的模板」,裡面包含了應用程式運行所需的一切。就像是一張光碟,你可以用它來產生容器。
- Container(容器):Image 的「運行實例」。就像你把光碟放進光碟機,它就跑起來了。一個 Image 可以同時產生很多個 Container。
- Dockerfile:一個文字檔,裡面寫了一連串指令,告訴 Docker 如何建構 Image。你可以把它想成是「Image 的食譜」。
- Registry(映像倉庫):存放 Image 的地方,最知名的就是 Docker Hub。就像 GitHub 是放程式碼的,Docker Hub 是放映像檔的。
這四個概念的關係是:你寫 Dockerfile → 用它建構 Image → 用 Image 啟動 Container → 把 Image 推到 Registry 分享給別人。理解這個流程,Docker 就學會一半了。
撰寫你的第一個 Dockerfile(Node.js 實戰)
來,我們用一個簡單的 Node.js Express 應用來示範。假設你的專案結構長這樣:
my-app/
├── package.json
├── package-lock.json
├── server.js
└── Dockerfile
Dockerfile 內容如下:
# 使用 Node.js 20 的官方映像作為基底
FROM node:20-alpine
# 設定工作目錄
WORKDIR /app
# 先複製 package 檔案(利用 Docker 快取層)
COPY package*.json ./
# 安裝依賴
RUN npm ci --only=production
# 複製其餘程式碼
COPY . .
# 暴露 port
EXPOSE 3000
# 啟動指令
CMD ["node", "server.js"]
這邊有個小技巧:我們先複製 package.json 再 npm ci,最後才複製程式碼。這樣當你只改了程式碼而沒改依賴時,Docker 會使用快取的 npm ci 結果,大幅加速建構速度。這是 Docker 新手最常忽略的優化。
Docker 常用指令速查表
以下是你每天都會用到的 Docker 指令,建議收藏起來:
# 建構映像檔
docker build -t my-app:latest .
# 啟動容器(背景執行 + port 映射)
docker run -d -p 3000:3000 --name my-app my-app:latest
# 查看執行中的容器
docker ps
# 查看所有容器(含已停止的)
docker ps -a
# 查看容器日誌
docker logs my-app
docker logs -f my-app # 即時追蹤
# 進入容器內部(除錯用)
docker exec -it my-app sh
# 停止 / 刪除容器
docker stop my-app
docker rm my-app
# 刪除映像檔
docker rmi my-app:latest
# 清理未使用的資源
docker system prune
我個人最常用的組合是 docker logs -f 搭配 docker exec -it,除錯的時候超方便。新手常犯的錯誤是忘記加 -d(detach),結果容器佔住了終端機,按 Ctrl+C 又把容器殺掉了。
Docker Compose:多容器應用的救星
真實的後端專案通常不只一個服務。你可能有 Node.js API Server、PostgreSQL 資料庫、Redis 快取、Nginx 反向代理……用 docker run 一個一個啟動?太瘋狂了。
這時候就需要 Docker Compose。它讓你用一個 docker-compose.yml 檔案定義所有服務,然後一行指令全部啟動。如果你想深入了解,可以參考Docker Compose 多容器部署教學。
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
pgdata:
然後只要執行 docker compose up -d,所有服務就啟動了。要停止就 docker compose down。簡單到不行。
當你的容器化應用規模更大時,可能就需要考慮用 Kubernetes K8s 入門教學 來做容器編排了。
Volume 掛載與 Port 映射
Docker 容器預設是隔離的,這代表兩件事:容器內的資料在容器刪除後就消失了,而且外部無法直接存取容器內的服務。要解決這兩個問題,就需要 Volume 和 Port Mapping。
Volume(資料卷)有三種用法:
- Named Volume:
-v pgdata:/var/lib/postgresql/data,Docker 管理的持久化儲存,適合資料庫 - Bind Mount:
-v $(pwd)/src:/app/src,把本機目錄掛進容器,開發時超好用,改程式碼即時生效 - tmpfs Mount:存在記憶體中,容器停止就消失,適合暫存敏感資料
Port Mapping 的語法是 -p 主機port:容器port。例如 -p 8080:3000 代表把容器的 3000 port 映射到主機的 8080 port。搭配 Nginx 反向代理教學 可以實現更靈活的流量管理。
正式環境 Dockerfile 最佳實踐
開發用的 Dockerfile 和正式環境的差很多。以下是幾個重要的最佳實踐:
1. Multi-stage Build(多階段建構)
這是最重要的技巧。把「建構」和「執行」分成不同階段,最終映像檔只包含執行所需的最小內容:
# 第一階段:建構
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 第二階段:執行
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]
2. 使用 .dockerignore
跟 .gitignore 一樣的概念,避免把不必要的檔案複製進映像檔:
node_modules
.git
.env
*.md
tests/
coverage/
3. 不要用 root 運行
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -s /bin/sh -D appuser
USER appuser
4. 固定版本號:用 node:20.11-alpine 而不是 node:latest,避免不可預期的更新。
這些最佳實踐在設計 REST API 版本控制教學 中提到的 API 部署時同樣適用。
Docker Hub 與推送映像檔
Docker Hub 是最大的公開映像倉庫,你可以在上面找到幾乎所有主流軟體的官方映像。當然,你也可以把自己的映像推上去分享。
推送步驟:
# 登入 Docker Hub
docker login
# 標記映像(加上你的帳號名稱)
docker tag my-app:latest yourusername/my-app:1.0.0
# 推送
docker push yourusername/my-app:1.0.0
如果是公司專案,通常會用私有 Registry,像是 AWS ECR、Google Container Registry、或自架的 Harbor。設定方式大同小異,就是把 Docker Hub 的網址換成私有 Registry 的網址。
建議養成給映像打版本標籤的習慣(1.0.0、1.1.0),不要只用 latest。這樣回滾的時候才知道要回到哪個版本。
結語:容器化只是開始
Docker 真的是現代後端工程師的必備技能,不誇張。學會 Docker 之後,你會發現部署變得無比輕鬆,「在我電腦上可以跑」這句話也會從你的字典中消失。
不過,Docker 只是容器化旅程的起點。當你的服務越來越多、流量越來越大,你還需要學習容器編排(Kubernetes)、CI/CD 整合、監控與日誌收集等進階主題。
我的建議是:先把今天學到的東西實際動手做一遍。找一個你手邊的小專案,寫個 Dockerfile,跑起來,然後用 Docker Compose 加個資料庫。親手操作一次,比看十篇教學都有用。
容器化的世界很大,但入門其實不難。現在就打開你的終端機,輸入 docker --version,開始你的 Docker 之旅吧!
繼續閱讀
Kubernetes K8s 入門完整教學:從 Pod 到部署微服務應用的完整指南
Kubernetes(K8s)是現代雲端部署的標準工具,但入門曲線陡峭讓很多工程師望而卻步。本文從最基本的概念開始,用清楚的類比解釋 Pod、Service、Deployment 的關係,再帶你一步一步部署一個包含前端、後端和資料庫的微服務應用,讓你真正理解 K8s 的威力。
相關文章
Kubernetes K8s 入門完整教學:從 Pod 到部署微服務應用的完整指南
Kubernetes(K8s)是現代雲端部署的標準工具,但入門曲線陡峭讓很多工程師望而卻步。本文從最基本的概念開始,用清楚的類比解釋 Pod、Service、Deployment 的關係,再帶你一步一步部署一個包含前端、後端和資料庫的微服務應用,讓你真正理解 K8s 的威力。
Nginx 反向代理設定教學:從零開始搞懂負載均衡
完整的 Nginx 反向代理與負載均衡設定教學,從基礎安裝到 upstream 配置、健康檢查、SSL 終止一次搞定。附上實用的 nginx.conf 範例和常見踩坑解法。
你可能也喜歡
探索其他領域的精選好文