
Container Runtime:把環境變成可重複的最小單位
容器化最大的價值不是「跑起來」,而是「到哪裡都跑得起來」。 Container Runtime 是整個基礎設施的執行層,它負責建立容器、管理網路、掛載儲存與控制生命週期。只要這一層標準化,後續的部署、監控與 CI/CD 才能一致化。
如果沒有標準化的 runtime,你會面臨:
- 每台機器環境不同,部署結果不一致
- 同一個服務在不同環境行為不同
- 回滾與重建都需要「人腦記憶」
架構概覽
flowchart LR Dev[開發者] --> Build[Build Image] Build --> Registry[Container Registry] Registry --> Host[Docker Host] Host --> ContainerA[API Container] Host --> ContainerB[Admin Container] Host --> ContainerC[Worker Container] Portainer[Portainer] --> Host
核心概念
-
Image 與 Container 的差異
- Image 是不可變的模板,Container 是運行中的實例。
- 這讓「部署」變成下載 image 並啟動,降低環境漂移。
- 最佳實務:避免在容器內做手動修改,一切變更要回到 image。
-
Docker Compose 作為宣告式部署
- 透過 YAML 描述服務、網路、環境變數與 volume。
- 一份 Compose 可重複使用,降低手動操作成本。
- 對小團隊而言,Compose 就是一套「輕量級部署標準」。
-
容器網路(Bridge / Overlay)
- Bridge 提供單機容器間的通訊。
- 多機部署時可擴展到 Overlay(Swarm/K8s)。
- 設計重點:網路命名與隔離,避免所有容器都在同一網段。
-
Volume 與資料持久化
- 容器是可重建的,資料必須落在 volume 或外部儲存。
- 特別是資料庫與上傳檔案,必須明確指定掛載路徑。
- 常見錯誤:把重要資料留在容器內,重建時資料會消失。
-
管理與可視化
- Portainer 提供 GUI 來管理容器、logs、資源用量。
- 小團隊可用它建立一致的操作流程。
- 但仍需搭配權限管理,避免所有人都能直接重啟 production。
使用情境(具體場景)
- 一致化開發與部署:開發端用 Docker build,正式環境也用同一個 image,避免「我這邊可以」的問題。
- 快速回復:容器壞掉時直接重啟或重建,減少人工排查成本。
- 多服務部署:API、Admin、Worker 同時部署在一台主機上,但環境相互隔離。
- Dev/Test 快速複製:用同一份 compose 在本機或測試機啟動服務,縮短啟動時間。
實作範例 / 設定範例
1) Dockerfile 範例(Node.js)
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]2) Docker Compose 範例(API + Redis)
version: "3.9"
services:
api:
image: registry.example.com/api:1.2.0
ports:
- "3000:3000"
environment:
NODE_ENV: production
depends_on:
- redis
redis:
image: redis:7
volumes:
- redis-data:/data
volumes:
redis-data:3) 容器網路檢視與測試
# 查看 network
docker network ls
# 查看 container IP
docker inspect api | jq '.[0].NetworkSettings.Networks'
# 在容器內測試連線
docker exec -it api sh -c "apk add --no-cache curl && curl http://redis:6379"4) Portainer 部署
docker volume create portainer_data
docker run -d \
-p 9000:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest5) 資源限制與重啟策略
# docker-compose.resources.yaml
version: "3.9"
services:
api:
image: registry.example.com/api:1.2.0
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
memory: 256M
restart: always常見問題與風險
-
資料遺失: 如果沒有用 volume 持久化,容器刪掉資料就消失。資料庫與上傳檔案必須明確掛載。
- 避免方式:為重要服務建立獨立 volume,並列入備份清單。
-
Image 漂移: 使用
latest容易導致版本不一致,部署時行為不同。建議使用明確版本號。- 避免方式:每次 build 使用 tag(如 commit SHA),並在 registry 保留前一版。
-
資源競爭: 多容器同時跑在一台主機上,若沒有資源限制,可能互相搶 CPU/記憶體。應搭配
--memory或 compose 限制。- 避免方式:先設定保守上限,再依監控調整。
-
安全權限: 容器預設以 root 執行容易造成安全風險。應在 Dockerfile 中建立非 root 使用者。
- 避免方式:使用
USER node或自建 user。
- 避免方式:使用
-
日誌爆量: 容器 log 無限制增長會耗盡磁碟。需設定 log rotation 或外部收集。
- 避免方式:設定
--log-opt max-size或使用 fluentd/otel。
- 避免方式:設定
優點
- 部署流程一致,環境可重複
- 容器隔離降低相互影響
- 可快速擴展與回復
缺點 / 限制
- 容器網路與 storage 的概念成本較高
- 若缺乏治理,容易出現 image 漂移與資源爭用
- 單機 Docker 不等於高可用,仍需要上層編排(Swarm/K8s)
落地檢查清單
- 是否固定 image 版本號
- 是否明確定義 volume
- 是否限制容器資源(CPU/記憶體)
- 是否有 log rotation
- 是否建立管理入口(如 Portainer)