「在 RHEL 企業級 Linux 環境中,使用 Podman 進行無 Root (Rootless) 容器化,並透過 Systemd 實現開機自啟與服務自癒,才是符合 Production-Ready 標準的終極部署架構。」
在 Day 12 中,我們實作了 /health 與 /stats 監控 API,並將其與 Ansible 巡檢進行整合。今天我們將進入核心部署章節——使用 Podman 撰寫 Containerfile 進行應用程式容器化,並透過 Systemd (angelina.service) 實現服務化託管!
為了符合企業級 Linux 的安全性要求,我們不採用傳統 Docker 的 Root 權限守護進程,而是使用 RHEL 原生的 Podman 進行非 Root 容器打包與管理。
在 RHEL 系統上,Containerfile 是 Podman 的標準容器建構檔。我們採用 Python 官方輕量映像檔,設定工作目錄為 /opt/angelina,並預先建立日誌與數據目錄:
Dockerfile
# Containerfile
FROM python:3.11-slim
# 設定環境變數:停用 Python 緩衝與 Pyc 寫入
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1
WORKDIR /opt/angelina
# 建立日誌與數據持久化目錄
RUN mkdir -p /var/log/angelina /opt/angelina/data /opt/angelina/config
# 複製並安裝依賴套件
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 複製應用程式原始碼與靜態資源
COPY app/ ./app/
COPY static/ ./static/
# 暴露 FastAPI 預設埠號 8080
EXPOSE 8080
# 啟動 Uvicorn 服務
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
為了確保打包映像檔時不會將敏感金鑰(如 service-account.json)、SQLite 資料庫(conversations.db)或巨大的向量檔案包含進去,我們在專案根目錄建立了 .containerignore:
# .containerignore
.git
.gitignore
__pycache__
*.pyc
*.pyo
*.pyd
.env
data/
config/service-account.json
var/log/
.venv/
這不僅大幅縮小了容器映像檔的體積,更防止了敏感金鑰意外打包至映像檔中的資安風險。
為了讓容器能在 RHEL 伺服器開機時自動啟動,並在發生 crash 時自動恢復,我們將 Podman 容器包裝為 Systemd 服務(angelina.service):
[Unit]
Description=Angelina AI Financial Expert Agent Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/angelina
ExecStartPre=-/usr/bin/podman stop angelina
ExecStartPre=-/usr/bin/podman rm angelina
ExecStart=/usr/bin/podman run --rm --name angelina \
-p 8080:8080 \
-v /opt/angelina/data:/opt/angelina/data:Z \
-v /opt/angelina/config:/opt/angelina/config:Z \
-v /var/log/angelina:/var/log/angelina:Z \
angelina-agent:latest
ExecStop=/usr/bin/podman stop -t 10 angelina
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
1.-v ...:Z 標籤:在 RHEL 開啟 SELinux 的環境下,:Z 標籤會自動為掛載目錄重寫 SELinux 安全上下文,防止 Podman 因權限不足無法讀寫資料庫與日誌。
2.ExecStartPre 預先清理:確保每次啟動服務前,都會先停止並移除舊的殘留容器,保證啟動狀態的乾淨。
3.Restart=always:服務崩潰時會在 10 秒內自動重啟,實現真正的無人值守運維。
透過 Containerfile 與 angelina.service 的結合,我們完成了生產環境部署的最後一塊拼圖:
明天(Day 14)我們將進入 deploy/deploy.sh 一鍵部署腳本實作,探討如何整合 Git pull、Podman build 與 Systemd reload,實現完全自動化的 CI/CD 部署流程!
明日預告:【Day 14】自動化部署管線:deploy.sh 腳本實作與 CI/CD 流程整合