Docker 不是唯一選擇?重新審視 Linux 上的 Web 應用部署策略
近年來,「部署 = Docker + 容器編排(Kubernetes、ECS 等)」已成為幾乎無可挑戰的常識。正因如此,將 Web 應用直接以 進程 + systemd 服務 的方式部署在 Linux 伺服器上,往往會被視為過時。
但實際情況是:
- 單一 Web 應用
- 小型團隊 / 簡單基礎設施
- 本地部署或嚴格受規範的環境
在這些情境下,以 systemd 服務部署往往更簡單、更穩定、且更符合運維需求。
本文將整理在 Linux 上使用 systemd.service 部署 Web 應用時,相較於 Docker 的優勢,以及 在哪些情況下 systemd 部署更有幫助。
1. 簡要說明 systemd 與 Docker
先簡短說明兩者概念:
- Docker
- 將應用打包成映像(image)
- 以容器(container)方式執行
-
「整個環境封裝 → 在任何地方都能一致執行」是其強項
-
systemd
- 現代 Linux 發行版的預設 init 系統
- 在啟動時啟動服務(daemon),服務失效時自動重啟,並管理日誌
- 以
*.service單元檔定義並管理進程
Docker 是「封裝應用環境的工具」,而 systemd 是「管理 Linux 進程的工具」。
兩者並非競爭關係,實際上常見的做法是:在 Docker 容器內部使用 systemd,或讓 systemd 管理 Docker 守護進程本身。
本文聚焦於「完全不使用 Docker,僅以 systemd 運行 Web 應用」的情境。
2. 使用 systemd.service 部署的優點
2-1. 簡化層級:減少一層
使用 Docker 時,運維棧會多出以下組件:
- Docker 守護進程
- 映像建置管道
- 映像倉庫(Registry)
- 容器執行時的權限/權限管理
相對地,systemd 部署只需:
- 在 OS 上安裝所需的執行時(Python / Node / Java 等)
- 部署應用程式碼
- 以 systemd 服務註冊並執行
這是一個相對簡單的結構。
對於小型專案或內部服務:
- 「映像建置 → 推送 → 拉取 → 重新部署」的流程往往成為負擔
- 直接 SSH 進入伺服器,執行
git pull+systemctl restart更快、更直觀
2-2. 與 Linux 的天然整合
systemd 是 Linux 的「門面」,與 OS 級別功能緊密結合:
- 日誌:
journalctl -u myapp.service可即時查看服務日誌 - 自動啟動:
systemctl enable myapp.service只需一次,即可在開機時自動啟動 - 資源限制(cgroup):
MemoryMax、CPUQuota等選項可輕鬆控制資源 - 相依性管理:
After=network.target/After=postgresql.service等可控制啟動順序
若使用 Docker,則需要分別查看容器內外的日誌、資源、網路,並判斷問題是屬於容器還是宿主機。
對於僅運行一兩個 Web 服務,從運維/除錯角度看,systemd 直結結構更直觀。
2-3. 低資源佔用
Docker 本身的開銷不大,但實際上往往伴隨:
- 多個映像/層級佔用磁碟
- 未使用的容器佔用空間
- 容器日誌/卷管理
systemd 部署只需 OS + 執行時 + 應用程式碼,對於磁碟/記憶體緊張的環境更為輕量。
在多台小型 VM 或嵌入式/低規格伺服器上,systemd 會顯得更輕盈。
2-4. 網路結構更直觀
使用 Docker 時,需理解:
- 容器內部 IP 與埠
- 與宿主機的埠映射
- 桥接網路 / 覆蓋網路
而 systemd 服務直接綁定宿主機的 IP/埠,防火牆規則亦以宿主機為基準,網路除錯更簡單:
- 埠是否開啟?
- 防火牆是否阻擋?
- 與同一伺服器其他服務是否衝突?
減少了一層容器網路的複雜度。
2-5. 某些環境無法使用 Docker
實際上這種情況比想像中常見:
- 金融、公共、醫療等嚴格受規範的本地環境
- 運維政策禁止容器執行
- 網路受限,無法存取外部映像倉庫
在這些情況下,唯一可行的選擇往往是「OS + systemd」。掌握 systemd 後,即可實現:
- 自動重啟
- 日誌管理
- 資源限制
- 健康檢查(間接)
3. systemd.service 範例:Web 應用部署
以下以 gunicorn 服務 Django/Flask 為例。
3-1. 單元檔範例
/etc/systemd/system/myapp.service:
[Unit]
Description=My Web Application (Gunicorn)
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/srv/myapp
EnvironmentFile=/etc/myapp.env
ExecStart=/usr/bin/gunicorn \
--workers 4 \
--bind 0.0.0.0:8000 \
config.wsgi:application
# 失效時自動重啟
Restart=on-failure
RestartSec=5
# 資源限制範例(可選)
# MemoryMax=512M
# CPUQuota=50%
[Install]
WantedBy=multi-user.target
環境變數可放在 /etc/myapp.env:
DJANGO_SETTINGS_MODULE=config.settings.prod
SECRET_KEY=super-secret-key
DATABASE_URL=postgres://...
後續指令非常簡單:
# 註冊服務並開機自動啟動
sudo systemctl enable myapp.service
# 啟動 / 停止 / 重啟
sudo systemctl start myapp.service
sudo systemctl restart myapp.service
sudo systemctl stop myapp.service
# 查看狀態 / 日誌
sudo systemctl status myapp.service
sudo journalctl -u myapp.service -f
對熟悉 Linux 伺服器的運維團隊而言,無需額外學習即可直接上手。
4. 何時更適合使用 systemd 而非 Docker?
總結來說,以下情境值得考慮 systemd 部署:
4-1. 單一/小型服務,無需複雜編排
- 只運行 1~2 個 Web 應用
- 資料庫使用 RDS 等托管服務
- 伺服器數量不多(1~5 台)
在此情況下,Docker + 編排的成本往往高於收益,systemd + 簡易部署腳本(Ansible、Fabric 等)即可滿足需求。
4-2. 運維團隊熟悉 Linux 服務
- 現有系統大多以 systemd 為基礎
- 運維人員已熟悉
systemctl、journalctl、rsyslog、logrotate
在這種環境下,直接在現有運維棧上部署 Web 應用更高效。
4-3. 嚴格規範或 Docker 被限制
- 金融、公共、國防、醫療等
- 封閉網路/內部網路
- 容器安全評估/認證繁瑣
Docker 的引入本身可能成為風險,使用 OS + systemd 是更安全、可驗證的做法。
4-4. 想減少宿主機與容器之間的隔離
- 需要直接使用
strace、perf、/proc進行調優 - 想一次性觀察網路/檔系統/資源問題
此時,直接在宿主機上執行 Web 應用比在容器內部更方便。
5. 當然 Docker 仍有其適用場景
雖然已說明 systemd 的優勢,但 Docker 仍有明顯好處:
- 以映像建置 → 在任何地方都能一致執行
- 減少本地/測試/生產環境差異
- 與 CI/CD 流程自然整合
- 多服務(Web + worker + cron + DB 等)組合
若需要在多台伺服器或多個環境重複部署相同堆疊,或團隊內部環境差異大,Docker 可能是更佳選擇。
最終關鍵在於:
「我們的服務規模、團隊結構、基礎設施環境,哪一個工具能更簡單、更穩定、更易運維?」

6. 結語:工具不是重點,情境才是關鍵
在 Linux 上部署 Web 應用時,不是「一定要 Docker」也不是「Docker 就好」。
- 單一服務、簡單基礎設施、嚴格規範環境 → systemd.service 可能更實際
- 多服務、不同環境、頻繁部署/擴容 → Docker 可能帶來更大價值
如果已經在使用 Linux 伺服器,值得思考:
- 「這個服務真的需要 Docker 嗎?」
- 「用 systemd 會不會更簡單?」
工具只是達成目標的手段,簡單與易運維才是長期最具生產力的關鍵。
目前沒有評論。